【问题标题】:Flutter - Trouble preserving focus between routesFlutter - 无法在路线之间保持焦点
【发布时间】:2019-01-31 23:34:24
【问题描述】:

我有一个表单,它使用FocusNodes 直观地指示表单的哪个部分处于活动状态。一个字段将 PopupRoute 扩展为一种弹出“键盘”。我的问题是,当我按下该字段时,键盘会弹出,但焦点的视觉效果不会出现。

来自FocusNode 的侦听器的一些调试显示它获得焦点但立即失去焦点。我想是因为新的PopupRoute有了新的FocusScopeNode,所以我的FocusNode没有焦点了。

如何在另一条路线上保持该领域的焦点?我试过了:

  • 在所有构建方法中使用FocusScope.of(context).reparentIfNeeded(focusNode),但没有做任何事情(我不太了解这个函数tbh)
  • 将当前的FocusScope.of(context) 传递给我的自定义PopupRoute 以供使用。这确实有效,但弹出后,我无法再集中注意力(我猜它被丢弃了?)

代码方面,我在现场点击时调用requestFocus,并在 initState 中添加此侦听器:

    widget.focusNode.addListener(() {
      print(widget.focusNode);
      if (widget.focusNode.hasFocus) {
        Navigator.of(context).push(
          CustomKeyboardPopupRoute(
            state: widget.state,
            position: //position stuff,
            focusScopeNode: FocusScope.of(context), //the second of my ideas which didn't quite work above
          )
        ).then((_) {
           widget.focusNode.unfocus();
        });
    }); 

【问题讨论】:

    标签: focus flutter


    【解决方案1】:

    你走在正确的轨道上,确实这是因为FocusScopeNode

    让你的键盘路由扩展TransitionRoute:

    class CustomKeyboardPopupRoute extends TransitionRoute {
      @override
      bool get opaque => false;
    
      @override
      Duration get transitionDuration => Duration(milliseconds: 300);
    
      @override
      Iterable<OverlayEntry> createOverlayEntries() sync* {
        yield OverlayEntry(
          opaque: false,
          maintainState: true,
          builder: _buildKeyboard,
        );
      }
    
      Widget _buildKeyboard(BuildContext context) {
        final positionAnimation = Tween(begin: Offset(0.0, 1.0), end: Offset.zero).animate(animation);
        return SlideTransition(position: positionAnimation, child: Align(
          alignment: Alignment.bottomCenter,
          child: ...
        ),);
      }
    }
    

    【讨论】:

    • 太棒了,谢谢!通过yieldModalBarrier 之前_buildKeyboard
    • 我不明白这个答案。自定义过渡如何与 FocusScope 有任何关系?抄送@卢卡斯
    • 过渡与它没有任何关系。但是当您定义自定义路线时,您必须注意转换。这个答案的重点:如果您想将焦点保持在父路由的TextField 上,则不能将PopupRoute 用于自定义键盘。
    • 它们以不同的方式扩展父类,其中一个区别是PopupRoute 创建了一个新的FocusScopeNodeTransitionRoute 没有。
    【解决方案2】:

    非常感谢。

    Iterable<OverlayEntry> createOverlayEntries() sync* {
        yield OverlayEntry(
          opaque: false,
          maintainState: true,
          builder: (content) {
            return ModalBarrier(dismissible: true);
          }
        );
        yield OverlayEntry(
          opaque: false,
          maintainState: true,
          builder: _buildContent,
        );
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-12
      • 2015-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多