【发布时间】:2019-11-13 01:21:23
【问题描述】:
问题是我想在文本字段值的末尾添加“,00”在 iOS 设备中效果很好,但在 android 中光标移动到文本字段中值的起点。所以,我无法添加“,00”。
【问题讨论】:
-
请贴一些代码sn-p,到目前为止你已经尝试过什么。
标签: flutter
问题是我想在文本字段值的末尾添加“,00”在 iOS 设备中效果很好,但在 android 中光标移动到文本字段中值的起点。所以,我无法添加“,00”。
【问题讨论】:
标签: flutter
我在设置 TextEditingController 时遇到了同样的问题,这对我有用。
controller.text = someString;
controller.selection = TextSelection.fromPosition(TextPosition(offset: controller.text.length));
TextSelection.fromPosition() 执行以下操作(来自文档):
在给定的文本位置创建一个折叠的选择。一个倒塌的 选择以相同的偏移量开始和结束,这意味着它包含 零个字符,而是用作文本中的插入点。
【讨论】:
Material Textfield 来执行此操作,CupertinoTextfield 的行为与预期相同.. 将操纵文本分配给其 TextEditingController 光标始终位于末尾。因为我认为这应该是文本字段的默认行为,所以我向 Flutter 团队提交了一个问题,因为如果你有类似这样的不同行为,这会扼杀 Flutter 的目的。它并不是真正的多平台。我敢肯定这是由于不同的团队..但是,嘿,应该就事情达成一致..无论如何..再次感谢优雅的解决方法。
我用这个解决了我的问题
这会将您的光标设置在文本字段的末尾。
您可以随时随地调用代码,当它被调用时,它会设置光标位置。
或者简单地将这段代码放在文本字段的onChanged()方法中
final val = TextSelection.collapsed(offset: _textTEC.text.length);
_textTEC.selection = val;
【讨论】:
这对我有用:
_inputCtrl.value = TextEditingValue(
text: suggestion,
selection: TextSelection.collapsed(offset: suggestion.length),
);
https://github.com/flutter/flutter/issues/11416#issuecomment-507040665
【讨论】:
这对我来说就像一个魅力。
myController.text = newText;
myController.selection = TextSelection(
baseOffset: newText.length,
extentOffset: newText.length)
【讨论】:
查看TextEditingController的text的setter的注释,上面说[文本]和[选择]不应该同时改变,但是对于电话输入,我们'想为输入应用某种格式(例如'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,
);
}
【讨论】:
似乎可行的解决方案如下:
为文本字段的构造函数提供一个 TextEditingController 参数:
var myTextEditingController = TextEditingController();
var myTextField = TextField(..., controller: myTextEditingController);
在文本字段中设置新文本时,请像这样使用 TextEditingController:
myTextEditingController.value.copyWith(
text: newText,
selection: TextSelection(
baseOffset: newText.length,
extentOffset: newText.length
)
)
这似乎非常复杂,但它似乎是解决 Flutter 文本字段中光标未更新问题的唯一解决方案。
【讨论】:
copyWith?
您可以使用 .. 运算符如果您在控制器中设置值如下:
final _controller = TextEditingController()..text = txtValue
..selection = TextSelection.collapsed(offset: txtValue.length);
)
我认为它在设置值运行时非常有用。
【讨论】:
以下代码非常适合我。
_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))
);
【讨论】:
创建一个新的 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
);
}
}
【讨论】:
我有一个TextField,并且我有一个定期向其附加文本的方法。我想水平滚动到该文本字段的最右端以查看最后附加的字符串,或者我想将光标移动到最后附加的字符。
对我有用的唯一技巧是使用scrollController,并在每次附加文本时调用jump() 方法:
TextField(
scrollController: scrollController,
controller: textFieldController
)
现在跳转到TextField的末尾:
scrollController.jumpTo( scrollController.position.pixels+500);
【讨论】:
如果您的新值太长。您应该将视图滚动到新的光标位置。
TextEditingController 和ScrollController 添加到TextField。记得在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);
});
【讨论】:
您需要一个FocusNode 并设置TextSelection 来放置光标。
这里的代码可能是一个开始:Position cursor at end of TextField when focused?
【讨论】:
根据documentation,将文本和位置设置在一起的可能方法是使用value...像这样:
_controller.value = _controller.value.copyWith(text: newText, selection: newSelection)
【讨论】:
有很多解决方案,但在下面的代码中,我合并了来自 Github 和 SO 的最佳答案。
下面的 Dart >= 2.12 具有 null-safety 并使用最新的 TextSelection APIs
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,
);
}
}
【讨论】:
我也遇到了类似的问题,试图将TextEditingController.text 中的文本更改为匹配NumberFormat("###,###,###.##") 内部onChanged 的格式化字符串,同时尝试保留当前光标位置并最终执行以下操作:
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),
);
}
},
)
【讨论】: