【问题标题】:Flutter: How to insert text in middle of text field textFlutter:如何在文本字段文本中间插入文本
【发布时间】:2020-05-20 07:23:12
【问题描述】:

我有一个颤振的文本字段和一个表情符号选择器按钮。在选择表情符号时,我需要将其插入当前光标位置。 我怎样才能做到这一点? 目前使用TextEditingController 我只能附加表情符号。我无法获取当前光标偏移量。

emojiPicker() {
    return EmojiPicker(
      rows: 3,
      columns: 7,
      recommendKeywords: null,
      indicatorColor: flujoAccentColor,
      onEmojiSelected: (emoji, category) {
        print(emoji);
        _messageInputController.text =
            _messageInputController.text + emoji.emoji;
     }
    );
  }

【问题讨论】:

    标签: flutter dart


    【解决方案1】:
    1. 使用_txtController.selection 获取选择(或光标位置)。
    2. 用选定的表情符号替换选择。
    3. 然后修复控制器的选择(或光标位置)
    import 'package:emoji_picker/emoji_picker.dart';
    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MaterialApp(home: HomePage()));
    }
    
    class HomePage extends StatefulWidget {
      @override
      _HomePageState createState() => _HomePageState();
    }
    
    class _HomePageState extends State<HomePage> {
      TextEditingController _messageInputController;
    
      @override
      void initState() {
        _messageInputController = TextEditingController();
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text("Demo"),
          ),
          body: SafeArea(
            child: Column(
              children: <Widget>[
                EmojiPicker(
                  rows: 3,
                  columns: 7,
                  recommendKeywords: null,
                  indicatorColor: Colors.red,
                  onEmojiSelected: (emoji, category) {
                    String text = _messageInputController.text;
                    TextSelection textSelection = _messageInputController.selection;
                    String newText = text.replaceRange(
                        textSelection.start, textSelection.end, emoji.emoji);
                    final emojiLength = emoji.emoji.length;
                    _messageInputController.text = newText;
                    _messageInputController.selection = textSelection.copyWith(
                      baseOffset: textSelection.start + emojiLength,
                      extentOffset: textSelection.start + emojiLength,
                    );
                  },
                ),
                TextField(
                  controller: _messageInputController,
                ),
              ],
            ),
          ),
        );
      }
    }
    

    这样你不仅可以在光标位置插入选中的表情符号,还可以替换部分选中的文字

    【讨论】:

    • 为了显示表情符号选择器,首先我通过关注其他焦点节点来手动隐藏键盘。所以文本选择开始将是-1。这给了我 text.replaceRange 的范围错误。
    • 我还尝试在 selection.start 上的 textediting 控制器侦听器返回的位置插入表情符号,但问题是因为我的文本字段没有聚焦它返回 -1。如何在不显示键盘的情况下使文本字段成为焦点并显示外部表情符号选择器。
    • 当您手动隐藏键盘时,在隐藏它之前,捕获当前点并将其存储在一个变量中。那么你会在它被关闭之前的最后一个位置?
    • 谢谢!这个答案为我节省了很多时间。
    • 这很好用!如果光标的位置是-1,我还必须提出另一种解决方案。我做了以下事情:var cursorPos = textController.selection.base.offset; if(cursorPos &lt; 0) { textController.text += emoji.toString(); }
    【解决方案2】:

    这是对 CrazyLazyCat 答案的轻微修改。

    void _insertText(String inserted) {
      final text = _controller.text;
      final selection = _controller.selection;
      final newText = text.replaceRange(selection.start, selection.end, inserted);
      _controller.value = TextEditingValue(
        text: newText,
        selection: TextSelection.collapsed(offset: selection.baseOffset + inserted.length),
      );
    }
    

    注意事项

    • _controllerTextEditingController
    • 如果您同时更改文本和选择,那么您应该使用TextEditingValue 而不是单独更改它们(因为它们都会触发更新)。
    • 一般情况下,如果您插入一些内容,您希望光标出现在之后再插入,因此TextSelection.collapsed 带有调整后的索引。

    【讨论】:

    • 我喜欢这种方法。虽然@we_more 对 CrazyLazyCat 的回答仍然有效: selection.start 可以是 -1 所以我们应该检查 base.offset 并在这种情况下附加文本。
    【解决方案3】:

    除了text.replaceRange,我还有另一个解决方案。

    你只需要:

    TextEditingController _tec;
    
    String youWillAddtoTEC = "your emoji or your clipboard data or else";
    
    String beforeCursorPositionAtTEC = tec.selection.textBefore(tec.text);
    
    String afterCursorPositionAtTEC = tec.selection.textAfter(tec.text);
    
    String result = beforeCursorPositionAtTEC + youWillAddtoTEC + afterCursorPositionAtTEC;
    

    然后将结果添加到 tec 或您需要的任何小部件:

    tec.text = result;
    

    选择或光标位置与上面相同,但如果您需要将光标放在“youWillAddToTEC”之后,您可以这样做:

    tec.selection = TextSelection.collapsed(offset: tec.selection.start + youWillAddtoTEC.lenght);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-11
      • 2021-02-26
      • 1970-01-01
      • 2020-07-13
      • 2020-06-29
      • 1970-01-01
      相关资源
      最近更新 更多