我创建了一个自定义窗口小部件MyDateTimePicker
,它基本上是一个TextFormField
,可显示日期并允许用户在点击时选择日期。现在,我的问题是,我想从父窗口小部件中的另一个事件更新当前选择/显示的日期。起初,我想到为TextEditingController
使用类似TextFormField
的控制器。不幸的是,我不确定该怎么做,所以我走了最后一条路,那就是对小部件状态使用全局键,并使用该键从父小部件中调用更新功能。就像很多人会说的那样,请避免使用全局键,因此我想改用控制器。我希望您能在可能的情况下帮助我如何为自定义小部件使用控制器。谢谢!
class MyDateTimePicker extends StatefulWidget {
const MyDateTimePicker(
{Key key,
this.labelText,
@required this.initialDate,
this.onValueChanged})
: super(key: key);
final String labelText;
final DateTime initialDate;
final ValueChanged<DateTime> onValueChanged;
@override
MyDateTimePickerState createState() => MyDateTimePickerState();
}
class MyDateTimePickerState extends State<MyDateTimePicker> {
final TextEditingController _controller = TextEditingController();
DateTime _selectedDate;
@override
void initState() {
super.initState();
_selectedDate = widget.initialDate;
_controller.text = DateFormat.yMMMd().format(_selectedDate);
}
// Called by the parent widget through a global key.
void setDate(DateTime date) {
_selectedDate = date;
_controller.text = DateFormat.yMMMd().format(_selectedDate);
}
Future<void> _selectDate(BuildContext context) async {
final DateTime picked = await showDatePicker(
context: context,
initialDate: _selectedDate,
firstDate: DateTime(1970, 8),
lastDate: DateTime(2101));
if (picked != null && picked != _selectedDate) {
_selectedDate = picked;
_controller.text = DateFormat.yMMMd().format(_selectedDate);
widget.onValueChanged(picked);
}
}
@override
Widget build(BuildContext context) {
return TextFormField(
controller: _controller,
decoration: InputDecoration(
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(5.0)),
),
contentPadding: const EdgeInsets.symmetric(vertical: 0.0),
labelText: widget.labelText,
prefixIcon: Icon(Icons.calendar_today),
suffixIcon: Icon(Icons.arrow_drop_down),
),
readOnly: true,
onTap: () {
_selectDate(context);
},
);
}
}
答案 0 :(得分:0)
您可以像这样将TextEditingController作为MyDateTimePicker小部件的参数传递:
class MyDateTimePicker extends StatefulWidget {
const MyDateTimePicker({
Key key,
this.labelText,
@required this.initialDate,
this.onValueChanged,
@required this.controller,
}) : super(key: key);
final String labelText;
final DateTime initialDate;
final ValueChanged<DateTime> onValueChanged;
final TextEditingController controller;
@override
MyDateTimePickerState createState() => MyDateTimePickerState();
}
class MyDateTimePickerState extends State<MyDateTimePicker> {
DateTime _selectedDate;
@override
void initState() {
super.initState();
_selectedDate = widget.initialDate;
widget.controller.text = DateFormat.yMMMd().format(_selectedDate);
}
// Called by the parent widget through a global key.
void setDate(DateTime date) {
_selectedDate = date;
widget.controller.text = DateFormat.yMMMd().format(_selectedDate);
}
Future<void> _selectDate(BuildContext context) async {
final DateTime picked = await showDatePicker(
context: context,
initialDate: _selectedDate,
firstDate: DateTime(1970, 8),
lastDate: DateTime(2101));
if (picked != null && picked != _selectedDate) {
_selectedDate = picked;
widget.controller.text = DateFormat.yMMMd().format(_selectedDate);
widget.onValueChanged(picked);
}
}
@override
Widget build(BuildContext context) {
return TextFormField(
controller: widget.controller,
decoration: InputDecoration(
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(5.0)),
),
contentPadding: const EdgeInsets.symmetric(vertical: 0.0),
labelText: widget.labelText,
prefixIcon: Icon(Icons.calendar_today),
suffixIcon: Icon(Icons.arrow_drop_down),
),
readOnly: true,
onTap: () {
_selectDate(context);
},
);
}
}