Flutter Widget Focus问题

时间:2019-01-04 21:06:17

标签: flutter flutter-layout flutter-focus

我已经创建了一个自定义窗口小部件以用于时间选择。

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

它是这样的: enter image description here

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

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

使用2个TimePickers检出表单图像: enter image description here

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

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

您可以在此处查看其代码: https://github.com/moti0375/tikal_time_tracker/blob/develop/lib/ui/time_picker.dart

任何想法都会受到赞赏。

1 个答案:

答案 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);
}