我已经创建了一个自定义窗口小部件以用于时间选择。
窗口小部件包含一个打开TimePicker的图标和一个TextFormField,以便用户可以手动键入时间值。
当用户键入一个值时,它会立即生效,并且在焦点关闭时,它会验证值并使用正确的时间格式更新该字段。
例如,如果用户键入8,然后单击下一个窗口小部件,它将更新为8:00
我想要的是,当用户键入StartTime,然后单击键盘的“下一步”按钮时,焦点将移至EndTime选择器。然后,当用户单击EndTime Picker上的Next按钮时,焦点将移至表单中的下一个小部件
问题在于FocusNode位于TimePicker自定义小部件(即StateFull)内部,我无法弄清楚如何将其暴露在其外部。
您可以在此处查看其代码: https://github.com/moti0375/tikal_time_tracker/blob/develop/lib/ui/time_picker.dart
任何想法都会受到赞赏。
答案 0 :(得分:0)
最后我想通了,
我没有在选择器窗口小部件(子窗口小部件)中创建FocusNode,而是在父窗口小部件(窗体)中创建了FocusNode并将其提供给其构造函数中的子窗口小部件,由此在父小部件上下文。
然后,我向子窗口小部件添加了一个请求焦点方法,以便父窗口小部件可以调用它们,并且FocusScope.of(context).requestFocus(focusNode);
在子窗口小部件内部但在父窗口小部件提供的focusNode上被调用。
这是代码的一部分:
子窗口小部件:
class TimeTrackerTimePicker extends StatefulWidget {
final FocusNode focusNode;
TimeTrackerTimePicker({ this.focusNode});
//This can be called from the parent widget with the parent context
void requestFocus(BuildContext context){
print("${this.pickerName} requestFocus...");
FocusScope.of(context).requestFocus(focusNode);
}
....
....
@override
State<StatefulWidget> createState() {
return TimePickerState();
}
}
状态类:
class TimePickerState extends State<TimeTrackerTimePicker> {
@override
Widget build(BuildContext context) {
return Container(
....
child: new Flexible(
child: new TextFormField(
textInputAction: TextInputAction.next,
focusNode: widget.focusNode, //linking to the focusNode
onFieldSubmitted: onSubmitButtonClicked,
decoration: InputDecoration(
hintText: widget.hint != null ? widget.hint : "",
contentPadding:
EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0))),
maxLines: 1,
controller: pickerController))
)
}
}
然后在需要设置焦点时在父窗口小部件中:
FocusNode focusNode;
TimeTrackerTimePicker timePicker;
@override
void initState() {
super.initState();
focusNode = new FocusNode();
timePicker = new TimeTrackerTimePicker(focusNode: focusNode);
}
.....
//request focus when required..
void requestPickerFocus(){
timePicker.requestFocus(context);
}