Flutter:通过按下后退按钮解除键盘时,不关注文本字段(多行)

Posted

技术标签:

【中文标题】Flutter:通过按下后退按钮解除键盘时,不关注文本字段(多行)【英文标题】:Flutter: Unfocus on textfield (multiline) when keyboard is dismissed via back button press 【发布时间】:2020-01-10 04:12:26 【问题描述】:

我有以下TextFormField

TextFormField(
  focusNode: inputFocusNode, 
  keyboardType: TextInputType.multiline,
  maxLines: null,
  minLines: 3,
)

当文本字段处于焦点时,会出现键盘。当按下电话返回按钮时,键盘消失,但文本字段上的光标仍然存在。

我知道您可以使用FocusScope.of(context).unfocus() 来移除光标或取消焦点。但是,似乎没有直接的方法来检测键盘关闭而不获得package

我该如何解决这个问题?

【问题讨论】:

我很困惑兄弟,因为每次您按下设备中的后退按钮时,它肯定会关闭设备键盘,但如果您想通过在键盘外单击来关闭它,您可以使用 FocusScope.of(context) .requestFocus(new FocusNode());并将其包装在 GestureDetector() 中并设置在 onTap 上。 或 FocusScope.of(context).unfocus(); 您好,谢谢您的回复。就像你说的,当按下设备后退按钮时,键盘肯定会被关闭(就像我在我的问题中提到的那样)。但是,除非我点击文本字段以外的其他内容,否则文本字段中的光标不会消失。当键盘被关闭时,我试图摆脱闪烁的光标。 例如,我可以用onTapunfocus 的文本字段创建一个gesturedetector。但这依赖于屏幕上的tapping。但是,当用户通过按下设备后退按钮关闭键盘时,从技术上讲,用户并没有在屏幕上tap 任何内容,因此不会关闭焦点,即使键盘已关闭。 您好,您在这个问题上有什么进展吗?我也有这个问题,不想用包。 【参考方案1】:

作为一个选项,您可以监听窗口指标的变化。

    给State类添加WidgetsBindingObserver接口 覆盖didChangeMetrics方法 在initStatedispose 方法中添加/删除监听器

查看完整代码:

import 'package:flutter/material.dart';

void main() 
  runApp(MaterialApp(home: Scaffold(body: Home())));


class Home extends StatefulWidget 
  @override
  _HomeState createState() => _HomeState();


class _HomeState extends State<Home> with WidgetsBindingObserver 
  final FocusNode inputFocusNode = FocusNode();

  @override
  void initState() 
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  

  @override
  Widget build(BuildContext context) 
    return Center(
      child: TextFormField(
        focusNode: inputFocusNode,
        keyboardType: TextInputType.multiline,
        maxLines: null,
        minLines: 3,
      ),
    );
  

  @override
  void didChangeMetrics() 
    super.didChangeMetrics();
    final value = WidgetsBinding.instance.window.viewInsets.bottom;
    if (value == 0) 
      inputFocusNode.unfocus();
    
  

  @override
  void dispose() 
    WidgetsBinding.instance.removeObserver(this);
    inputFocusNode.dispose();
    super.dispose();
  

【讨论】:

【参考方案2】:

用这个小部件包裹你的整个应用程序。

Listener(
 onPointerDown: (_) 
   FocusScopeNode currentFocus = FocusScope.of(context);
   if (!currentFocus.hasPrimaryFocus &&
   currentFocus.focusedChild != null) 
   currentFocus.focusedChild.unfocus();
  
 ,
 child: //MyApp()
)

当用户点击其他任何地方时,它也会移除焦点和光标。

【讨论】:

你知道为什么它需要成为整个应用程序的父级吗?我尝试将它放在树中的较低级别,但它不起作用 令人惊讶的是,这个“Listener”小部件做了“GestureDetector”无法实现的事情。这应该被标记为答案。谢谢大佬。【参考方案3】:

您可以检查是否可见键盘,当它不可见时,您可以调用unfocus() 方法。例如,要跟踪键盘,您可以使用这个库keyboard_visibility。示例代码:

FocusNode myFocusNode = FocusNode();

KeyboardVisibilityNotification().addNewListener(
    onChange: (bool visible) 
        if (!visible) 
            myFocusNode.unfocus()
        
    ,
);

【讨论】:

【参考方案4】:

我将其发布为答案,因为由于我的回购,我仍然无法发表评论。 对我来说@user10539074 的解决方案不起作用,因为它没有让文本字段只聚焦(键盘在尝试打开时立即关闭)。所以我添加了这条额外的行,它对我有用。

if (MediaQuery.of(context).viewInsets.bottom != 0)

     if (value == 0) 
          inputFocusNode.unfocus();
        

此检查的基本作用是仅在键盘已打开时才运行该代码。

【讨论】:

以上是关于Flutter:通过按下后退按钮解除键盘时,不关注文本字段(多行)的主要内容,如果未能解决你的问题,请参考以下文章

想知道在文本字段编辑 ios 期间按下键盘后退按钮的时间

颤振:如何在按下后退按钮时不退出应用程序

Android:为EditText打开键盘时处理后退按钮单击

在颤振中,按下后退按钮时如何返回上一个 URL?

检测后退按钮但不关闭对话框片段

按下后退时,EditText不会触发更改