【问题标题】:Flutter Widget Focus issueFlutter 小部件焦点问题
【发布时间】:2019-05-31 10:40:58
【问题描述】:

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

该小部件包含一个打开 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

任何想法将不胜感激。

【问题讨论】:

    标签: flutter focus flutter-layout


    【解决方案1】:

    终于想通了,

    我没有在选择器小部件(子小部件)中创建 FocusNode,而是在父小部件(表单)中创建了 FocusNode,并在其构造函数中将其提供给子小部件,由此创建的焦点节点在父小部件上下文。

    然后,我向子小部件添加了一个请求焦点方法,以便父小部件可以调用它们,并且在子小部件内部但在父小部件提供的 focusNode 上调用 FocusScope.of(context).requestFocus(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))
       )
     }
    }
    

    然后在父widget的时候需要设置焦点:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-26
      • 2021-11-10
      • 2022-01-16
      • 2010-12-08
      • 1970-01-01
      • 2016-04-14
      • 2023-03-29
      • 1970-01-01
      相关资源
      最近更新 更多