0

我已经为时间选择创建了一个自定义小部件。

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

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

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

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

使用 2 个 TimePicker 签出表单图像: 在此处输入图像描述

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

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

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

任何想法将不胜感激。

4

1 回答 1

4

最后我想通了,

我没有在选择器小部件(子小部件)中创建 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);
}
于 2019-01-20T11:16:11.973 回答