【问题标题】:How to make the scrollcontroller of a TextField follow the current position of the cursor in Flutter?如何使 TextField 的滚动控制器跟随 Flutter 中光标的当前位置?
【发布时间】:2022-01-05 02:16:45
【问题描述】:

我正在尝试创建一个自定义键盘,以便我的应用程序有自己的风格。我没有显示设备键盘,但现在我遇到的问题是,当我键入并且光标离开图像时,T​​extField 不会像使用设备键盘键入时那样自动跟随光标。有谁知道如何使滚动随光标移动,如果已经看到光标,那么它就不会移动?

Here我留下一段视频,展示我所说的内容,以便您更好地了解,起初我只是简单地给出一个用 GestureDetector 包裹的文本,以便 onTap 函数将我想要的文本添加到我的 textController .text 它看起来因为滚动不随光标移动,但后来我再次点击设备键盘,它确实随它移动,这是我想要的行为。我不得不把它放在驱动器链接中,因为 stackoverflow 不允许将视频放在这里。

我还留下了我的 TextField 代码,以便您可以看到它并告诉我是否有任何错误,这就是为什么它不能按我想要的那样工作。

class ValueInput extends StatefulWidget {
  const ValueInput({
    Key? key,
    required this.valueText,
  }) : super(key: key);

  final String valueText;

  @override
  State<ValueInput> createState() => _ValueInputState();
}

class _ValueInputState extends State<ValueInput> {
  TextEditingController textController = TextEditingController(text: '0');
  ScrollController scrollController = ScrollController();
  FocusNode nodo = FocusNode();
  int count = 0;

  void _insertText(
    TextEditingController controller,
    FocusNode node,
    String myText,
  ) async {
    Future<bool> focused() async {
      return node.hasFocus;
    }

    if (!node.hasFocus) {
      node.requestFocus();
    }
    await focused() == true;
    final text = controller.text;
    final textSelection = controller.selection;
    final newText = text.replaceRange(
      textSelection.start,
      textSelection.end,
      myText,
    );
    final myTextLength = myText.length;
    controller.text = newText;
    controller.selection = TextSelection.fromPosition(
        TextPosition(offset: textSelection.start + myTextLength));
  }

  @override
  Widget build(BuildContext context) {
    final Brightness brightness =
        WidgetsBinding.instance!.platformDispatcher.platformBrightness;
    final prefs = PreferenciasUsuario();
    final border = OutlineInputBorder(
      borderRadius: BorderRadius.circular(7),
      borderSide: BorderSide(
        width: 2.0,
        style: BorderStyle.solid,
        color: Tema.color3,
      ),
    );

    return Column(
      children: [
        GestureDetector(
          onTap: () async {
            count++;
            _insertText(textController, nodo, count.toString());
          },
          child: Text(
            'Valor ${widget.valueText}',
            style: MyTextStyles().defaultStyle.copyWith(color: Tema.blanco),
          ),
        ),
        SizedBox(height: 1.h(context)),
        SizedBox(
          height: 6.h(context),
          width: 25.w(context),
          child: TextField(
            focusNode: nodo,
            controller: textController,
            scrollController: scrollController,
            // readOnly: true,
            // showCursor: true,
            keyboardType: TextInputType.number,
            keyboardAppearance: (prefs.tema == 2)
                ? Brightness.light
                : (prefs.tema == 3)
                    ? Brightness.dark
                    : (brightness == Brightness.dark)
                        ? Brightness.dark
                        : Brightness.light,
            textAlign: TextAlign.center,
            style: MyTextStyles()
                .defaultStyle
                .copyWith(color: Tema.negro, fontSize: 14.sp(context)),
            decoration: InputDecoration(
              contentPadding: const EdgeInsets.all(10),
              enabledBorder: border,
              focusedBorder: border,
              disabledBorder: border,
              errorBorder: border,
              focusedErrorBorder: border,
              filled: true,
              fillColor: Tema.blanco,
            ),
          ),
        )
      ],
    );
  }
}

我希望有人可以帮助我,我唯一缺少的就是能够 100% 满足我的要求。

【问题讨论】:

    标签: flutter dart dart-null-safety


    【解决方案1】:

    我认为scrollController 参数是您的解决方案。 根据您希望在编辑器中收听文本更改的方式,您可以重用如下代码:

    String text = '';
    ScrollController _scrollController = ScrollController();
    
    scrollToCursor(String textFieldValue) {
        final isLonger = textFieldValue.length > text.length;
        text = textFieldValue;
        if (isLonger) _scrollController.animateTo(_scrollController.position.maxScrollExtent, duration: Duration(milliseconds: 300), curve: Curves.ease);
    }
    // use _scrollController.position.viewportDimension if text field is one line
    

    在build 方法内部:

    TextField(
                scrollController: _scrollController,
                //controller: _controller,  // if needed
                maxLines: null,
                onChanged: (value) {
                    scrollToCursor(value);
                }
    )
    

    当然,不要忘记像这样dispose()你的scrollController:

    @override
      void dispose() {
        _scrollController.dispose();
        super.dispose();
      }
    

    【讨论】:

    • 问题是我不使用 onChanged 函数,因为它是一个自定义键盘,所以我不知道是不是因为这个,但它只在开始时有效,有时它会停止在职的。我已经尝试过使用 ScrollController,但同样的事情发生在我身上,这就是为什么我决定询问是否有人知道如何做到这一点。还要感谢马特。
    猜你喜欢
    • 1970-01-01
    • 2021-05-22
    • 1970-01-01
    • 2019-01-01
    • 2019-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多