“字符串?”类型的值不能分配给“字符串”类型的变量颤动
Posted
技术标签:
【中文标题】“字符串?”类型的值不能分配给“字符串”类型的变量颤动【英文标题】:A value of type 'String?' can't be assign to variable of type 'String' flutter 【发布时间】:2021-09-20 08:29:16 【问题描述】:我在 val 上遇到了一个错误...它说,
“字符串?”类型的值不能分配给类型的变量 '细绳'。尝试更改变量的类型,或强制转换 右侧类型为“字符串”。
对此有误, 这段代码在下面的完整代码中
onChanged: (val) => setState(
() => _applyleavevalueChanged = val),
validator: (val)
setState(
() => _applyleavevalueToValidate = val);
return null;
,
onSaved: (val) => setState(
() => _applyleavevalueSaved = val),
我在 val 上遇到了一个错误...它说,
“字符串?”类型的值不能分配给类型的变量 '细绳'。尝试更改变量的类型,或强制转换 右侧类型为“字符串”。
这是我的完整源代码.....
文件:leaveapply.dart
import 'package:date_time_picker/date_time_picker.dart';
import 'package:dropdown_search/dropdown_search.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import './LeaveApply/BouncingButton.dart';
import './LeaveApply/leave_history.dart';
import 'LeaveApply/LeaveHistoryCard.dart';
import 'LeaveApply/datepicker.dart';
void main()
runApp(MaterialApp(
debugShowCheckedModeBanner: false,
home: LeaveApply(),
title: 'Leave Apply',
));
class LeaveApply extends StatefulWidget
@override
_LeaveApplyState createState() => _LeaveApplyState();
class _LeaveApplyState extends State<LeaveApply>
with SingleTickerProviderStateMixin
late Animation animation, delayedAnimation, muchDelayedAnimation, LeftCurve;
late AnimationController animationController;
final searchFieldController = TextEditingController();
late TextEditingController _applyleavecontroller;
String _applyleavevalueChanged = '';
String _applyleavevalueToValidate = '';
String _applyleavevalueSaved = '';
late TextEditingController _fromcontroller;
String _fromvalueChanged = '';
String _fromvalueToValidate = '';
String _fromvalueSaved = '';
late TextEditingController _tocontroller;
String _tovalueChanged = '';
String _tovalueToValidate = '';
String _tovalueSaved = '';
@override
void initState()
// ignore: todo
// TODO: implement initState
super.initState();
//SystemChrome.setEnabledSystemUIOverlays([]);
_applyleavecontroller =
TextEditingController(text: DateTime.now().toString());
_fromcontroller = TextEditingController(text: DateTime.now().toString());
_tocontroller = TextEditingController(text: DateTime.now().toString());
animationController =
AnimationController(duration: Duration(seconds: 3), vsync: this);
animation = Tween(begin: -1.0, end: 0.0).animate(CurvedAnimation(
parent: animationController, curve: Curves.fastOutSlowIn));
delayedAnimation = Tween(begin: 1.0, end: 0.0).animate(CurvedAnimation(
parent: animationController,
curve: Interval(0.2, 0.5, curve: Curves.fastOutSlowIn)));
muchDelayedAnimation = Tween(begin: -1.0, end: 0.0).animate(CurvedAnimation(
parent: animationController,
curve: Interval(0.3, 0.5, curve: Curves.fastOutSlowIn)));
@override
void dispose()
// ignore: todo
// TODO: implement dispose
animationController.dispose();
super.dispose();
final GlobalKey<FormState> _formkey = new GlobalKey<FormState>();
@override
Widget build(BuildContext context)
animationController.forward();
final double width = MediaQuery.of(context).size.width;
final double height = MediaQuery.of(context).size.height;
final GlobalKey<ScaffoldState> _scaffoldKey =
new GlobalKey<ScaffoldState>();
return AnimatedBuilder(
animation: animationController,
builder: (BuildContext context, Widget? child)
final GlobalKey<ScaffoldState> _scaffoldKey =
new GlobalKey<ScaffoldState>();
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
backgroundColor: Colors.white,
title: Text(
'Apply Leave',
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
),
),
leading: new IconButton(
icon: new Icon(
Icons.arrow_back_ios,
color: Colors.black87,
size: 18.0,
),
onPressed: () => Navigator.of(context).pop(),
),
centerTitle: true,
elevation: 1.0,
),
body: Form(
key: _formkey,
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 15.0,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Divider(
color: Colors.black.withOpacity(0.5),
height: 1,
),
SizedBox(
height: height * 0.05,
),
Transform(
transform: Matrix4.translationValues(
muchDelayedAnimation.value * width, 0, 0),
child: Text(
"Apply Leave Date",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
),
),
),
Padding(
padding: EdgeInsets.only(
top: 13,
),
child: Container(
// height: height * 0.06,
padding: EdgeInsets.only(
left: 10,
),
width: double.infinity,
decoration: BoxDecoration(
border: Border.all(color: Colors.black),
borderRadius: BorderRadius.circular(5),
),
child: Row(
children: [
Transform(
transform: Matrix4.translationValues(
muchDelayedAnimation.value * width, 0, 0),
child: Container(
width: width * 0.75,
child: DateTimePicker(
type: DateTimePickerType.date,
dateMask: 'dd/MM/yyyy',
controller: _applyleavecontroller,
//initialValue: _initialValue,
firstDate: DateTime(2000),
lastDate: DateTime(2100),
calendarTitle: "Leave Date",
confirmText: "Confirm",
enableSuggestions: true,
//locale: Locale('en', 'US'),
onChanged: (val) => setState(
() => _applyleavevalueChanged = val),
validator: (val)
setState(
() => _applyleavevalueToValidate = val);
return null;
,
onSaved: (val) => setState(
() => _applyleavevalueSaved = val),
),
),
),
Transform(
transform: Matrix4.translationValues(
delayedAnimation.value * width, 0, 0),
child: Icon(
Icons.calendar_today,
color: Colors.black,
),
),
],
),
),
),
SizedBox(
height: height * 0.03,
),
Transform(
transform: Matrix4.translationValues(
muchDelayedAnimation.value * width, 0, 0),
child: Text(
"Choose Leave Type",
style: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 14,
),
),
),
SizedBox(
height: height * 0.02,
),
Transform(
transform: Matrix4.translationValues(
delayedAnimation.value * width, 0, 0),
child: DropdownSearch<String>(
validator: (v) => v == null ? "required field" : null,
hint: "Please Select Leave type",
mode: Mode.MENU,
showSelectedItems: true,
items: [
"Medical",
"Family",
"Sick",
'Function',
'Others'
],
showClearButton: true,
onChanged: print,
),
),
SizedBox(
height: height * 0.05,
),
Transform(
transform: Matrix4.translationValues(
muchDelayedAnimation.value * width, 0, 0),
child: Text(
"Leave Date",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
),
),
),
Padding(
padding: EdgeInsets.only(
top: 13,
),
child: Container(
// height: height * 0.06,
padding: EdgeInsets.only(
left: 10,
),
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white38,
borderRadius: BorderRadius.circular(5),
boxShadow: [
BoxShadow(
offset: Offset(0, 1),
color: Colors.black12,
)
]),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Transform(
transform: Matrix4.translationValues(
muchDelayedAnimation.value * width, 0, 0),
child: Icon(
Icons.calendar_today,
color: Colors.black,
),
),
Transform(
transform: Matrix4.translationValues(
muchDelayedAnimation.value * width, 0, 0),
child: Padding(
padding: const EdgeInsets.all(6.0),
child: Container(
padding: const EdgeInsets.only(left: 4.0),
width: width * 0.28,
decoration: BoxDecoration(
color: Colors.white38,
boxShadow: [
BoxShadow(
offset: Offset(0, 1),
blurRadius: 2,
color: Colors.black26,
)
]),
child: CustomDatePicker(
controller: _fromcontroller,
title: "From",
onchanged: (val) =>
setState(() => _fromvalueChanged = val),
validator: (val)
setState(
() => _fromvalueToValidate = val);
return null;
,
saved: (val) =>
setState(() => _fromvalueSaved = val),
),
),
),
),
Transform(
transform: Matrix4.translationValues(
muchDelayedAnimation.value * width, 0, 0),
child: Icon(
Icons.arrow_forward,
color: Colors.black,
),
),
Transform(
transform: Matrix4.translationValues(
delayedAnimation.value * width, 0, 0),
child: Padding(
padding: const EdgeInsets.all(6.0),
child: Container(
padding: const EdgeInsets.only(left: 4.0),
width: width * 0.28,
decoration: BoxDecoration(
color: Colors.white38,
boxShadow: [
BoxShadow(
offset: Offset(0, 1),
blurRadius: 2,
color: Colors.black26,
)
],
),
child: CustomDatePicker(
controller: _tocontroller,
title: "To",
onchanged: (val) => setState(()
_tovalueChanged = val;
print(val);
),
validator: (val)
setState(() => _tovalueToValidate = val);
return null;
,
saved: (val) =>
setState(() => _tovalueSaved = val),
),
),
),
),
],
),
),
),
SizedBox(
height: height * 0.05,
),
Transform(
transform: Matrix4.translationValues(
muchDelayedAnimation.value * width, 0, 0),
child: Text(
"Apply Leave Date",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
),
),
),
Transform(
transform: Matrix4.translationValues(
delayedAnimation.value * width, 0, 0),
child: Padding(
padding: EdgeInsets.only(
top: 13,
),
child: Container(
// height: height * 0.06,
height: height * 0.25,
width: double.infinity,
decoration: BoxDecoration(
border: Border.all(color: Colors.black),
borderRadius: BorderRadius.circular(5),
),
child: TextFormField(
//autofocus: true,
minLines: 1,
maxLines: 10,
keyboardType: TextInputType.multiline,
decoration: InputDecoration(
suffixIcon: searchFieldController.text.isNotEmpty
? IconButton(
icon: Icon(Icons.clear),
onPressed: () => WidgetsBinding.instance
?.addPostFrameCallback((_) =>
searchFieldController.clear()))
: null,
border: InputBorder.none,
contentPadding: EdgeInsets.all(7),
),
),
),
),
),
SizedBox(
height: height * 0.05,
),
Transform(
transform: Matrix4.translationValues(
muchDelayedAnimation.value * width, 0, 0),
child: Text(
"Attach Document",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
),
),
),
Transform(
transform: Matrix4.translationValues(
delayedAnimation.value * width, 0, 0),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
onTap: () async ,
child: Text(
"Click ???? to Upload Documents",
style: TextStyle(
color: Color(0xff2876bd),
),
),
),
),
),
SizedBox(
height: 15,
),
Transform(
transform: Matrix4.translationValues(
delayedAnimation.value * width, 0, 0),
child: Bouncing(
onPress: () ,
child: Container(
//height: 20,
width: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: Color(0xff2876bd),
),
child: Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Request Leave",
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
),
),
),
),
SizedBox(
height: 50,
),
Column(
children: [
InkWell(
child: Text(
'LeaveHistory',
),
onTap: ()
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => LeaveHistory(
// leavetype: '',
// description: '',
// status: '',
// requesteddate: '',
// verifieddate: '',
)),
);
,
)
],
),
SizedBox(
height: 50,
)
],
),
),
),
),
);
,
);
【问题讨论】:
在val
的末尾添加!
,如val!
。能解决问题吗?
【参考方案1】:
_applyleavevalueChanged
的值类型是String
和
val
的值类型是String?
如果val
可以是null
_applyleavevalueChanged = val ?? ''; // '' is the default value in case val is null
或
if (val != null)
_applyleavevalueChanged = val!; // ! mark that the val is definitely not null
【讨论】:
【参考方案2】:你得到的错误来自空安全,String?
类型意味着它可以是String
或null
,但你的变量只接受String
,而不接受null
。
为此,您可以通过添加 ! 来“强制”使用“非空”变量。在变量的末尾,但这样做时要小心。
_applyleavevalueToValidate = val!
您可以在官方文档中了解更多关于 null-safety 语法和原则的信息:https://flutter.dev/docs/null-safety。
https://api.flutter.dev/flutter/material/DropdownButton-class.html.
【讨论】:
是的,成功解决了....谢谢【参考方案3】:您可以像这样简单地设置默认值。例如,
String? a;
String x = a ?? "default value";
【讨论】:
以上是关于“字符串?”类型的值不能分配给“字符串”类型的变量颤动的主要内容,如果未能解决你的问题,请参考以下文章
错误:“AppStateNotifier”类型的值不能分配给“Widget”类型的变量