Flutter Widget 焦点问题

Mot*_*tov 1 focus flutter flutter-layout

我创建了一个用于时间选择的自定义小部件。

该小部件包含一个可打开 TimePicker 的图标和一个 TextFormField,以便用户可以手动键入时间值。

它是这样的: 在此输入图像描述

当用户键入一个值时,它会立即验证,并且当焦点关闭时,它会验证该值并使用正确的时间格式更新字段。

例如,如果用户键入 8,然后单击下一个小部件,它将更新为 8:00

使用 2 个 TimePickers 检查表单图像: 在此输入图像描述

我想要的是,当用户输入 StartTime,然后单击键盘的 Next 按钮时,焦点将移动到 EndTime 选择器。然后,当用户单击 EndTime Picker 上的“Next”按钮时,焦点将移动到表单中的下一个小部件

问题是 FocusNode 位于 TimePicker 自定义小部件(即 StateFull)内部,我无法弄清楚如何将其暴露在外部。

您可以在这里查看它的代码: https: //github.com/moti0375/tikal_time_tracker/blob/develop/lib/ui/time_picker.dart

任何想法将不胜感激。

Mot*_*tov 7

终于我想通了

我没有在选择器小部件(子小部件)内创建 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();
   }
  }
Run Code Online (Sandbox Code Playgroud)

状态类:

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))
   )
 }
}
Run Code Online (Sandbox Code Playgroud)

然后在父小部件中需要设置焦点时:

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);
}
Run Code Online (Sandbox Code Playgroud)