【问题标题】:Flutter TextField - How to support submission on <ENTER> _and_ newline on <SHIFT-ENTER>Flutter TextField - 如何支持 <ENTER> 上的提交 _and_ <SHIFT-ENTER> 上的换行符
【发布时间】:2021-03-21 06:30:31
【问题描述】:

我正在开发一个包含聊天功能的 Flutter Web 应用程序。

我想包含一个普通的输入功能,用户可以在其中输入文本并将其发送到聊天流中。如今,聊天应用程序的一个标准功能是在 &lt;ENTER&gt;send 并在 &lt;SHIFT-ENTER&gt; 上执行换行符,或此的一些变体。

目前我一次只能实现一个这些功能。如果您将TextFieldkeyboardType 设置为TextInputType.multiline,那么&lt;ENTER&gt;&lt;SHIFT-ENTER&gt; 总是执行换行,似乎没有办法覆盖此行为。

如果您的TextFieldTextInputType.text,您可以捕获&lt;ENTER&gt; 并发送,但尝试捕获&lt;SHIFT-ENTER&gt; 以添加换行符不起作用。我尝试通过onKey 处理程序手动抓取按键并将\n 插入controller.text,但似乎TextInputType.text 根本不适合多行,所以它不能很好地播放。

只是想知道是否有其他开发人员遇到过这种情况或提出了任何合适的解决方案。理想情况下,解决方案也适用于 android/ios。对我来说,我决定使用 TextInputType.text 并暂时放弃多行功能。

谢谢

【问题讨论】:

    标签: flutter flutter-layout flutter-web


    【解决方案1】:

    为了它的价值,我能够炮制一个合理的解决方案,我将在下面发布,以防有​​人自己遇到这个问题。

    我将文本字段包装在一个键盘侦听器中,当它看到&lt;Enter&gt; 时,它调用我的onSend 函数。我以前试过这个,但我想早先我错过了RawKeyEventDataWeb 的演员表,这让我可以捕获isShiftPressed 以允许&lt;SHFT-ENTER&gt; 上的新行而不强制发送。不幸的是,我不得不添加一些 hacky 代码来删除按 Enter 时添加的 \n,但对于功能性 + 现代消息传递来说,这是一个很小的代价。

    RawKeyboardListener(
       focusNode: focusNode,
       onKey: handleKeyPress,
       child: TextField(
            controller: messageController,
            minLines: 1,
            maxLines: null,
            textInputAction: TextInputAction.done,
            style: normalTextStyle,
            keyboardType: TextInputType.multiline,
            decoration: InputDecoration(
                 isDense: true,
                 hintText: 'Type a message',
                 hintStyle: TextStyle(
                      fontSize: 16,
                      color: Color(0xFF474749),
                 ),
                 border: InputBorder.none,
            ),
        ),
    )
    
    void handleKeyPress(event) {
    if (event is RawKeyUpEvent && event.data is RawKeyEventDataWeb) {
      var data = event.data as RawKeyEventDataWeb;
      if (data.code == "Enter" && !event.isShiftPressed) {
        final val = messageController.value;
        final messageWithoutNewLine =
            messageController.text.substring(0, val.selection.start - 1) +
                messageController.text.substring(val.selection.start);
        messageController.value = TextEditingValue(
          text: messageWithoutNewLine,
          selection: TextSelection.fromPosition(
            TextPosition(offset: messageWithoutNewLine.length),
          ),
        );
        _onSend();
      }
    }
    }
    

    【讨论】:

      【解决方案2】:

      这可以通过将FocusNode 添加到TextField 来实现。将焦点节点置于小部件的状态。

      late final _focusNode = FocusNode(
        onKey: (FocusNode node, RawKeyEvent evt) {
          if (!evt.isShiftPressed && evt.logicalKey.keyLabel == 'Enter') {
            if (evt is RawKeyDownEvent) {
              _sendMessage();
            }
            return KeyEventResult.handled;
          }
          else {
            return KeyEventResult.ignored;
          }
        },
      );
      

      在您的build 函数中,在创建TextField 时添加焦点。

      TextField(
        autofocus: true,
        controller: _textController,
        focusNode: _focusNode,
      )
      

      【讨论】:

        【解决方案3】:

        在输入中禁用Enter 键并在没有按下ctrl 键时发送它的最佳方法是直接在输入上通过focusNode,这样您就不必删除额外的新行。

        class _InputTextState extends State<InputText> {
          late final _focusNode = FocusNode(onKey: handleKeyPress);
         
          @override
          Widget build(BuildContext context) {
            return TextField(
              focusNode: _focusNode,
            );
          }
        
          KeyEventResult handleKeyPress(FocusNode focusNode, RawKeyEvent event) {
            // handles submit on enter
            if (kIsWeb &&
                event.isKeyPressed(LogicalKeyboardKey.enter) &&
                !event.isControlPressed &&
                !event.isShiftPressed) {
              widget.onSubmit();
            // handled means that the event will not propagate
              return KeyEventResult.handled;
            }
            return KeyEventResult.ignored;
          }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-06-29
          • 1970-01-01
          • 2015-05-24
          • 1970-01-01
          • 2015-05-21
          • 2015-12-06
          • 1970-01-01
          相关资源
          最近更新 更多