如何在 flutter 中刷新小部件树上的 'if condition'?
How can i refresh 'if condition' on widget tree in flutter?
class CustomDateAndTime extends StatefulWidget {
const CustomDateAndTime({Key? key}) : super(key: key);
@override
_CustomDateAndTimeState createState() => _CustomDateAndTimeState();
}
class _CustomDateAndTimeState extends State<CustomDateAndTime> {
bool checkDate = false;
TextEditingController controller = TextEditingController();
String dateText = '';
late DateTime date;
var formatter = new DateFormat('d MMM, yyyy');
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
child: SizedBox(
width: MediaQuery.of(context).size.width,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(
flex: 4,
child: datePicker(context),
),
Expanded(
flex: 1,
child: Padding(
padding: EdgeInsets.only(top: 15),
child: Icon(Icons.date_range_outlined),
),
),
if (checkDate == true)
Expanded(
flex: 1,
child: Padding(
padding: EdgeInsets.only(top: 15),
child: IconButton(
icon: Icon(Icons.close),
onPressed: () {
setState(() {
controller.clear();
checkDate = false;
});
},
),
),
),
],
),
),
);
}
TextFormField datePicker(BuildContext context) {
return TextFormField(
readOnly: true,
controller: controller,
onTap: () async {
date = (await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2021, 8),
lastDate: DateTime(2050),
))!;
if (date.day == DateTime.now().day) {
controller.text = "TODAY";
checkDate = true;
} else if (date.day == DateTime.now().day + 1) {
controller.text = "TOMORROW";
checkDate = true;
} else {
controller.text = formatter.format(date);
checkDate = true;
}
},
);
}
}
在此代码中,如果输入了日期,我将添加一个删除按钮,但为此,if 块需要再次工作。但它不起作用。虽然它是 'statefull widget',但它不在 if 块内。
概括;输入日期后将添加一个新按钮。我怎样才能做到这一点 ? .................................................... ..................................................... .....................
您需要在选择日期后运行 setState。例如
Future<void> _selectDate(BuildContext context) async {
final DateTime picked = await showDatePicker(
context: context,
initialDate: selectedDate,
firstDate: DateTime(2015, 8),
lastDate: DateTime(2101));
if (picked != null && picked != selectedDate)
setState(() {
selectedDate = picked;
});
}
Stateful Widgets 在触发 setState()
方法时重建、重绘屏幕。所以,当像“checkDate”这样的状态变量被任何代码块改变时,你也应该触发 setState() 方法。
最佳做法是使用 setState 方法包装您的重新分配行:
if (date.day == DateTime.now().day) {
controller.text = "TODAY";
setState((){ checkDate = true;});
} else if (date.day == DateTime.now().day + 1) {
controller.text = "TOMORROW";
setState((){ checkDate = true;});
} else {
controller.text = formatter.format(date);
setState((){ checkDate = true;});
}
if block 没有调用的原因是因为它只在构建小部件时第一次调用,所以当您稍后更改它的值时不会再次调用。
有很多解决方案,每次你想更改时最简单的一个 checkDate 变量像那样将语句放在 setState() 中
setState(() => checkDate = false);
确保小部件再次创建所以代码输入if block
或者使用 ValueListenableBuilder 效率更高
class CustomDateAndTime extends StatefulWidget {
const CustomDateAndTime({Key? key}) : super(key: key);
@override
_CustomDateAndTimeState createState() => _CustomDateAndTimeState();
}
class _CustomDateAndTimeState extends State<CustomDateAndTime> {
bool checkDate = false;
TextEditingController controller = TextEditingController();
String dateText = '';
late DateTime date;
var formatter = new DateFormat('d MMM, yyyy');
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
child: SizedBox(
width: MediaQuery.of(context).size.width,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(
flex: 4,
child: datePicker(context),
),
Expanded(
flex: 1,
child: Padding(
padding: EdgeInsets.only(top: 15),
child: Icon(Icons.date_range_outlined),
),
),
if (checkDate == true)
Expanded(
flex: 1,
child: Padding(
padding: EdgeInsets.only(top: 15),
child: IconButton(
icon: Icon(Icons.close),
onPressed: () {
setState(() {
controller.clear();
checkDate = false;
});
},
),
),
),
],
),
),
);
}
TextFormField datePicker(BuildContext context) {
return TextFormField(
readOnly: true,
controller: controller,
onTap: () async {
date = (await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2021, 8),
lastDate: DateTime(2050),
))!;
if (date.day == DateTime.now().day) {
controller.text = "TODAY";
checkDate = true;
} else if (date.day == DateTime.now().day + 1) {
controller.text = "TOMORROW";
checkDate = true;
} else {
controller.text = formatter.format(date);
checkDate = true;
}
},
);
}
}
在此代码中,如果输入了日期,我将添加一个删除按钮,但为此,if 块需要再次工作。但它不起作用。虽然它是 'statefull widget',但它不在 if 块内。 概括;输入日期后将添加一个新按钮。我怎样才能做到这一点 ? .................................................... ..................................................... .....................
您需要在选择日期后运行 setState。例如
Future<void> _selectDate(BuildContext context) async {
final DateTime picked = await showDatePicker(
context: context,
initialDate: selectedDate,
firstDate: DateTime(2015, 8),
lastDate: DateTime(2101));
if (picked != null && picked != selectedDate)
setState(() {
selectedDate = picked;
});
}
Stateful Widgets 在触发 setState()
方法时重建、重绘屏幕。所以,当像“checkDate”这样的状态变量被任何代码块改变时,你也应该触发 setState() 方法。
最佳做法是使用 setState 方法包装您的重新分配行:
if (date.day == DateTime.now().day) {
controller.text = "TODAY";
setState((){ checkDate = true;});
} else if (date.day == DateTime.now().day + 1) {
controller.text = "TOMORROW";
setState((){ checkDate = true;});
} else {
controller.text = formatter.format(date);
setState((){ checkDate = true;});
}
if block 没有调用的原因是因为它只在构建小部件时第一次调用,所以当您稍后更改它的值时不会再次调用。
有很多解决方案,每次你想更改时最简单的一个 checkDate 变量像那样将语句放在 setState() 中
setState(() => checkDate = false);
确保小部件再次创建所以代码输入if block
或者使用 ValueListenableBuilder 效率更高