如何在文本字段中颤动的值末尾设置光标位置?
how to set cursor position at the end of the value in flutter in textfield?
我想在文本字段值的末尾添加 ,00
。
它在 iOS 设备中运行良好,但在 android 中光标移动到文本字段中值的起点。因此,我无法添加 ,00
.
您需要 FocusNode
并设置 TextSelection
来放置光标。
这里的代码可能是一个开始:Position cursor at end of TextField when focused?
似乎有效的解决方案如下:
为文本字段的构造函数提供一个 TextEditingController 参数:
var myTextEditingController = TextEditingController();
var myTextField = TextField(..., controller: myTextEditingController);
在文本字段中设置新文本时,请像这样使用 TextEditingController:
myTextEditingController.value.copyWith(
text: newText,
selection: TextSelection(
baseOffset: newText.length,
extentOffset: newText.length
)
)
这看起来非常复杂,但它似乎是解决 Flutter 文本字段中光标未更新问题的唯一方法。
我用这个
解决了我的问题
这会将您的光标设置在文本字段的末尾。
您可以随时随地调用代码,它会在调用时设置光标位置。
或者简单地将此代码放在文本字段onChanged()
的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()
执行以下操作(来自文档):
Creates a collapsed selection at the given text position. A collapsed
selection starts and ends at the same offset, which means it contains
zero characters but instead serves as an insertion point in the text.
查看了TextEditingController
的text
的setter
的注释,里面说[text]和[selection]不能同时改,但是对于 phone 输入,我们希望为输入应用某种格式(例如“131 1111 1111”),同时将光标始终保持在末尾。
所以我只使用了自定义的 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 class,扩展 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)
根据 documentation 将文本和位置一起设置的可能方法是使用 value
... 像这样:
_controller.value = _controller.value.copyWith(text: newText, selection: newSelection)
有很多解决方案,但在下面的代码中,我合并了 Github 和 SO 的最佳答案。
下面的代码对 Dart >= 2.12 具有空安全性,并使用最新的 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);
以防您的新值太长。您应该将视图滚动到新的光标位置。
- 将
TextEditingController
和 ScrollController
添加到 TextField
。
记得init/dispose他们在initState
和dispose
TextField(
controller: controller,
scrollController: scrollController,
)
- 为
TextEditingController
设置新值和光标位置
controller.text = newValue;
controller.selection = TextSelection.fromPosition(TextPosition(offset: controller.text.length));
- 滚动视图到位置
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));
我想在文本字段值的末尾添加 ,00
。
它在 iOS 设备中运行良好,但在 android 中光标移动到文本字段中值的起点。因此,我无法添加 ,00
.
您需要 FocusNode
并设置 TextSelection
来放置光标。
这里的代码可能是一个开始:Position cursor at end of TextField when focused?
似乎有效的解决方案如下:
为文本字段的构造函数提供一个 TextEditingController 参数:
var myTextEditingController = TextEditingController(); var myTextField = TextField(..., controller: myTextEditingController);
在文本字段中设置新文本时,请像这样使用 TextEditingController:
myTextEditingController.value.copyWith( text: newText, selection: TextSelection( baseOffset: newText.length, extentOffset: newText.length ) )
这看起来非常复杂,但它似乎是解决 Flutter 文本字段中光标未更新问题的唯一方法。
我用这个
解决了我的问题这会将您的光标设置在文本字段的末尾。
您可以随时随地调用代码,它会在调用时设置光标位置。
或者简单地将此代码放在文本字段onChanged()
的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()
执行以下操作(来自文档):
Creates a collapsed selection at the given text position. A collapsed selection starts and ends at the same offset, which means it contains zero characters but instead serves as an insertion point in the text.
查看了TextEditingController
的text
的setter
的注释,里面说[text]和[selection]不能同时改,但是对于 phone 输入,我们希望为输入应用某种格式(例如“131 1111 1111”),同时将光标始终保持在末尾。
所以我只使用了自定义的 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 class,扩展 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)
根据 documentation 将文本和位置一起设置的可能方法是使用 value
... 像这样:
_controller.value = _controller.value.copyWith(text: newText, selection: newSelection)
有很多解决方案,但在下面的代码中,我合并了 Github 和 SO 的最佳答案。
下面的代码对 Dart >= 2.12 具有空安全性,并使用最新的 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);
以防您的新值太长。您应该将视图滚动到新的光标位置。
- 将
TextEditingController
和ScrollController
添加到TextField
。
记得init/dispose他们在initState
和dispose
TextField(
controller: controller,
scrollController: scrollController,
)
- 为
TextEditingController
设置新值和光标位置
controller.text = newValue;
controller.selection = TextSelection.fromPosition(TextPosition(offset: controller.text.length));
- 滚动视图到位置
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));