I want to add ,00
at the end of the value of the textfield.
It works well in iOS device, but in android cursor moves to starting point of the value in textfield. As a result, I'm unable to add ,00
.
I want to add ,00
at the end of the value of the textfield.
It works well in iOS device, but in android cursor moves to starting point of the value in textfield. As a result, I'm unable to add ,00
.
I've been having the same problem with setting a TextEditingController
and this is what worked for me.
controller.text = someString;
controller.selection = TextSelection.fromPosition(TextPosition(offset: controller.text.length));
TextSelection.fromPosition()
does the following (from the documentation):
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.
Edit - another version, which is a bit shorter and suggested by others here:
controller.text = someString;
controller.selection =
TextSelection.collapsed(offset: controller.text.length);
Material Textfield
, CupertinoTextfield
behaves as expected.. when assign a manipulated text to its TextEditingController
cursor is always at the end. As I thing that this should be the default behavior for a textfield I filed an Issue to the Flutter team as this kinda kills Flutter purpose if you have different behaviors like this.. it ain't really multi platform.. I'm sure that this is due to different teams.. but hey, the should agree on things.. Anyways.. thanks again for the elegant workaround. –
Carlenecarleton This worked for me:
_inputCtrl.value = TextEditingValue(
text: suggestion,
selection: TextSelection.collapsed(offset: suggestion.length),
);
https://github.com/flutter/flutter/issues/11416#issuecomment-507040665
TextInputFormatter
that is installed on the TextField
with inputFormatters
. –
Saprogenic I solved my issue by using this
this will set your cursor at the end in the textfield.
you can call the code from wherever and whenever it will set the cursor location when it is called.
or simple place this code in onChanged()
method of textfield
final val = TextSelection.collapsed(offset: _textTEC.text.length);
_textTEC.selection = val;
You can use .. operator If you are setting value in the controller as below:
final _controller = TextEditingController()..text = txtValue
..selection = TextSelection.collapsed(offset: txtValue.length);
)
I think it's very useful when you are setting value runtime.
Simple and easy solution to move cursor at the end of position after updating the text in textfield just add below line.
textController.selection =
TextSelection.collapsed(offset: textController.text.length);
This works for me like a charm.
myController.text = newText;
myController.selection = TextSelection(
baseOffset: newText.length,
extentOffset: newText.length)
The solution that seems to work is the following:
Give a TextEditingController argument to the constructor of your text field:
var myTextEditingController = TextEditingController();
var myTextField = TextField(..., controller: myTextEditingController);
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.
copyWith
? –
Tupungato Checked the notes of the setter
of TextEditingController
's text
, it says the [text] and the [selection] shouldn't be changed at the same time, however for the phone inputting, we'd like to apply some format for the input (e.g. '131 1111 1111') while keeping the cursor always at the end .
So I just use a customized TextEditingController
, it works!
class PhoneEditingController extends TextEditingController {
@override
set text(String newText) {
value = value.copyWith(
text: newText,
selection: TextSelection.collapsed(offset: newText.length),
composing: TextRange.empty,
);
}
In case your new value is too long. You should scroll the view to the new cursor position.
TextEditingController
and ScrollController
to TextField
.Remember to init/dispose them in initState
and 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);
});
scrollController
. I never realized that TextField
had one until today. –
Solanum the following code worked perfectly for me.
_controller.value = _controller.value.copyWith(
text: newText,
selection: TextSelection.fromPosition(
TextPosition(offset: newText.length),
),
);
Using _textController.text.length
as the cursor's base offset doesn't work if you want to add your special characters (in your case 00
) somewhere in the middle of the text. In such cases, the following solution should work:
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);
or you can do it like this, it's the same thing:
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))
);
Create a new Dart class, extending TextEditingController and you can use your custom TextController instead that behaves:
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
);
}
}
There are a lot of solutions but in the code below I've merged the best answers from Github and SO.
This below has null-safety for Dart >= 2.12 and uses latest TextSelection
APIs
import 'package:flutter/widgets.dart';
class TextEditingControllerWithEndCursor extends TextEditingController {
TextEditingControllerWithEndCursor({
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,
);
}
}
I have a TextField
, and I have a method that appends text to it periodically. I wanted to scroll horizontally to the rightmost end of that text field to see the last appended string, or I want to move the cursor to the last character appended.
The only trick that worked for me was to use a scrollController
, and call the jump()
method every time I append text:
TextField(
scrollController: scrollController,
controller: textFieldController
)
Now jump to the end of the TextField
:
scrollController.jumpTo( scrollController.position.pixels+500);
Use a StatefulWidget
and store a TextEditingController
.
class SampleTextFieldextends StatefulWidget {
const SampleTextField({super.key});
@override
State<SampleTextField> createState() => _SampleTextFieldState();
}
class _SampleTextFieldStateextends State<SampleTextField> {
late final TextEditingController controller = TextEditingController();
@override
Widget build(BuildContext context) {
return TextField(
controller: controller,
onChanged: (value) {
controller.text = value;
controller.selection =
TextSelection.collapsed(offset: controller.text.length);
},
onTap: () {
controller.selection =
TextSelection.collapsed(offset: controller.text.length);
},
onTapOutside: (event) {
FocusScope.of(context).unfocus();
},
);
}
}
This answer put curser at the end of the text field in right to left (ltr) languages like Farsi / Persian / Arabic.
I also had a similar problem trying to change the text in the TextEditingController.text
into a formatted string matching NumberFormat("###,###,###.##")
inside onChanged
while trying to preserve the current cursor location and ended up doing something like this:
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),
);
}
},
)
A simple example will help you.
if (int.parse(mintues) > 59) mintuesController.text = '59';
mintuesController.selection = TextSelection.fromPosition(
TextPosition(offset: mintues.length));
The easy way is
TextField(
decoration: InputDecoration(labelText: "Email"),
controller: TextEditingController.fromValue(TextEditingValue(text:
useremail,selection: TextSelection.collapsed(offset: useremail.length))),
onChanged: (value) => useremail= value,
)
in my case and because I'm using getx as state management, I solved the problem by:
TextField(
controller: TextEditingController.fromValue(TextEditingValue(
text: con.nominator1String.value,
selection: TextSelection.collapsed(
offset: con.nominator1String.value.length)))
)
con is my getx controller
To change text cursor after change not just end of the string but also middle of string you can use this snippet on onChange property of TextField
:
(newValue){
int changedPosition =
determineChangedPosition(previousTextFieldValue, newValue);
// Set the cursor position at the changed position
controller.selection = TextSelection.fromPosition(
TextPosition(offset: newValue.length == changedPosition
? changedPosition
: changedPosition + 1)),
);
}
use StatefullWidget
to store previousTextFieldValue
and here is determineChangedPosition
method:
int determineChangedPosition(String oldValue, String newValue) {
final minLength =
oldValue.length < newValue.length ? oldValue.length : newValue.length;
for (var i = 0; i < minLength; i++) {
if (oldValue[i] != newValue[i]) {
return i;
}
}
return minLength;
}
You need a FocusNode
and set TextSelection
to place the cursor.
The code here may be a start: Position cursor at end of TextField when focused?
According to the documentation the possible way to set the text and position together is using value
... like this:
_controller.value = _controller.value.copyWith(text: newText, selection: newSelection)
© 2022 - 2024 — McMap. All rights reserved.