如何在文本域中设置光标位置在颤振值的末尾?

我想在 textfield 的值的末尾添加 ,00

它在 iOS 设备中运行良好,但在 android 中,光标移动到 textfield 中值的起始点。因此,我无法添加 ,00

85185 次浏览

您需要一个 FocusNode并设置 TextSelection来放置光标。

这里的代码可能是一个开始: 当聚焦时,将光标定位在 TextField 的末尾?

看来有效的解决办法如下:

  1. 为文本字段的构造函数提供一个 TextEditingController 参数:

    var myTextEditingController = TextEditingController();
    var myTextField = TextField(..., controller: myTextEditingController);
    
  2. When setting the new text inside your text field, use the TextEditingController like that:

    myTextEditingController.value.copyWith(
    text: newText,
    selection: TextSelection(
    baseOffset: newText.length,
    extentOffset: newText.length
    )
    )
    

This seems extraordinary complicated for what it achieves but it seems to be the only solution to the problem of the cursor not being updated in Flutter text fields.

我用这个解决了我的问题

这将在文本字段的末尾设置光标。

您可以随时随地调用该代码,当它被调用时,它将设置光标位置。

或简单地将此代码放置在 textfield 的 onChanged()方法中

final val = TextSelection.collapsed(offset: _textTEC.text.length);
_textTEC.selection = val;

我在设置 TextEditingController的时候也遇到了同样的问题,这个方法对我很有效。

controller.text = someString;
controller.selection = TextSelection.fromPosition(TextPosition(offset: controller.text.length));

TextSelection.fromPosition()执行以下操作(根据文档) :

在给定的文本位置创建折叠选区 选择开始和结束在相同的偏移量,这意味着它包含 零个字符,而是作为文本中的插入点。

Edit (编辑)——另一个版本,稍微简短一点,这里有其他人的建议:

controller.text = someString;
controller.selection =
TextSelection.collapsed(offset: controller.text.length);

检查了 TextEditingControllertextsetter的注释,它说[文本]和[选择]不应该同时改变,但是对于手机输入,我们想为输入应用一些格式(例如’13111111111’) ,同时保持光标总是在最后。

所以我只是使用一个定制的 TextEditingController,它的工作原理!

class PhoneEditingController extends TextEditingController {


@override
set text(String newText) {
value = value.copyWith(
text: newText,
selection: TextSelection.collapsed(offset: newText.length),
composing: TextRange.empty,
);


}

下面的代码对我来说非常有效。

_controller.value = _controller.value.copyWith(
text: newText,
selection: TextSelection.fromPosition(
TextPosition(offset: newText.length),
),
);

如果您想在文本的中间添加特殊字符(在您的情况下是 00) ,那么使用 _textController.text.length作为光标的基偏移量是不起作用的。在这种情况下,以下解决方案应该奏效:

String specialChars = '00';
int length = specialChars.length;
// current cursor position, where you want to add your special characters
int cursorPos = _textController.selection.base.offset;
// the text before the point you want to add the special characters
String prefixText = _textController.text.substring(0, cursorPos);
// the text after the point ...
String suffixText = _textController.text.substring(cursorPos);


_textController.text = prefixText + specialChars + suffixText;
// set the cursor position right after the special characters
_textController.selection = TextSelection(baseOffset: cursorPos + length, extentOffset: cursorPos + length);

或者你可以这样做,这是一样的:

int cursorPos = _textController.selection.base.offset;
_textController.value = _textController.value.copyWith(
text: _textController.text.replaceRange(cursorPos, cursorPos, '00'),
selection: TextSelection.fromPosition(TextPosition(offset: cursorPos + 2))
);

这对我很有效:

_inputCtrl.value = TextEditingValue(
text: suggestion,
selection: TextSelection.collapsed(offset: suggestion.length),
);

Https://github.com/flutter/flutter/issues/11416#issuecomment-507040665

创建一个新的 Dart 类,扩展 TextEditingController,您可以使用自定义的 TextController 代替它的行为:

class TextController extends TextEditingController {


TextController({String text}) {
this.text = text;
}


set text(String newText) {
value = value.copyWith(
text: newText,
selection: TextSelection.collapsed(offset: newText.length),
composing: TextRange.empty
);
}
}

这对我来说太有用了。

myController.text = newText;
myController.selection = TextSelection(
baseOffset: newText.length,
extentOffset: newText.length)

根据 文件,设置文本和位置的可能方法是使用 value... 像这样:

_controller.value = _controller.value.copyWith(text: newText, selection: newSelection)

有很多解决方案,但在下面的代码中,我合并了来自 Github 和 SO 的最佳答案。

下面的代码对 Dart > = 2.12具有 null 安全性,并使用了最新的 TextSelection API

import 'package:flutter/widgets.dart';


class TextEditingControllerWithEndCursor extends TextEditingController {


TextEditingControllerWithCursorPosition({
String? text
}): super(text: text);


@override
set text(String newText) {
value = value.copyWith(
text: newText,
selection: TextSelection(
baseOffset: newText.length,
extentOffset: newText.length
),
composing: TextRange.empty,
);
}
}

你可以使用 ..操作符如果你在控制器中设置的值如下:

final _controller = TextEditingController()..text = txtValue
..selection = TextSelection.collapsed(offset: txtValue.length);


)

我认为它在设置值运行时时非常有用。

我有一个 TextField,还有一个定期向它追加文本的方法。我想水平滚动到该文本字段的最右端以查看最后一个附加的字符串,或者我想将光标移动到最后一个附加的字符。

唯一对我有用的技巧是使用 scrollController,并在每次添加文本时调用 jump()方法:

TextField(
scrollController: scrollController,
controller: textFieldController
)

现在跳到 TextField的结尾:

scrollController.jumpTo( scrollController.position.pixels+500);

如果您的新值太长,您应该将视图滚动到新的光标位置。

  1. TextEditingControllerScrollController添加到 TextField

记住在 initStatedispose中初始化/处理它们

TextField(
controller: controller,
scrollController: scrollController,
)
  1. TextEditingController设置一个新值和光标位置
controller.text = newValue;
controller.selection = TextSelection.fromPosition(TextPosition(offset: controller.text.length));
  1. 滚动视图到位置
Future.delayed(Duration(milliseconds: 50),(){
scrollController.jumpTo(scrollCtrl.position.maxScrollExtent);
});


我也遇到过类似的问题,当我试图将 TextEditingController.text中的文本更改为与 onChanged中的 NumberFormat("###,###,###.##")匹配的格式化字符串时,我试图保留当前的光标位置,结果是这样的:

TextFormField(
controller: controller,


onChanged: (value) {
final formatter = NumberFormat("###,###,###.##");
final amount = formatter.parse(value);


//allow user to enter any letter at the end without clearing it.
//otherwise if the user enters "." it would get truncated by
//the formatter
if (amount == 0 || value.startsWith(formatter.format(amount.floor()))) {
return;
}


final editor = controller.value;


//only do something if the IME is not in the middle of composing
if (editor.composing.isCollapsed) {
//offset is the position of the cursor
int offset = editor.selection.extentOffset;


final pretty = formatter.format(amount);


if(offset >= value.length) {
//set the offset to the length of the new string
offset = pretty.length;


} else {
//count how many chars are in the string to the left
//of the cursor position, excluding formatting chars [,.-]


final partial = value.substring(0, offset);
for (var unit in partial.codeUnits) {
if (unit >= 44 && unit <= 46) offset--;
}


//traverse the formatted string by the same number of
//characters skipping over the formatting chars [,.-].
int i = 0;
for (var unit in pretty.codeUnits) {
if (i++ >= offset) break;
if (unit >= 44 && unit <= 46) offset++;
}
//offset is now where the new cursor position should be
}


//finally update the controller to the new offset
controller.value = editor.copyWith(
text: pretty,
selection: TextSelection.collapsed(offset: offset),
composing: TextRange.collapsed(offset),
);
}
},
)

一个简单的例子会帮助你。

 if (int.parse(mintues) > 59) mintuesController.text = '59';
mintuesController.selection = TextSelection.fromPosition(
TextPosition(offset: mintues.length));

简单方便的解决方案 在更新 textfield 中的文本后移动位置末尾的光标,只需在下面添加一行即可。

textController.selection =
TextSelection.collapsed(offset: textController.text.length);