how to set cursor position at the end of the value in flutter in textfield?

FlutterText Cursor

Flutter Problem Overview


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.

Flutter Solutions


Solution 1 - Flutter

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.

Solution 2 - Flutter

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;

Solution 3 - Flutter

This worked for me:

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

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

Solution 4 - Flutter

This works for me like a charm.

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

Solution 5 - Flutter

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.

Solution 6 - Flutter

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,
  );

}

Solution 7 - Flutter

The solution that seems to work is the following:

  1. Give a TextEditingController argument to the constructor of your text field:

     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.

Solution 8 - Flutter

In case your new value is too long. You should scroll the view to the new cursor position.

  1. Add TextEditingController and ScrollController to TextField.

Remember to init/dispose them in initState and dispose

TextField(
controller: controller,
scrollController: scrollController,
)
  1. Set a new value and cursor position for the TextEditingController
controller.text = newValue;
controller.selection = TextSelection.fromPosition(TextPosition(offset: controller.text.length));
  1. Scroll the view to the position
Future.delayed(Duration(milliseconds: 50),(){
 scrollController.jumpTo(scrollCtrl.position.maxScrollExtent);
});

Solution 9 - Flutter

the following code worked perfectly for me.

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

Solution 10 - Flutter

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))
);

Solution 11 - Flutter

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
    );
  }
}

Solution 12 - Flutter

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);

Solution 13 - Flutter

You need a FocusNode and set TextSelection to place the cursor.

The code here may be a start: https://stackoverflow.com/questions/55019550/position-cursor-at-end-of-textfield-when-focused

Solution 14 - Flutter

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)

Solution 15 - Flutter

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 {

  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,
    );
  }
}

Solution 16 - Flutter

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),
      );
    }
  },
)

Solution 17 - Flutter

A simple example will help you.

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionParth BhanderiView Question on Stackoverflow
Solution 1 - FlutterjwehrleView Answer on Stackoverflow
Solution 2 - FlutterVicky SalunkheView Answer on Stackoverflow
Solution 3 - FlutterWilliamView Answer on Stackoverflow
Solution 4 - FlutterRoberto JuárezView Answer on Stackoverflow
Solution 5 - FlutterPratik ButaniView Answer on Stackoverflow
Solution 6 - FlutterrayworksView Answer on Stackoverflow
Solution 7 - FlutterJohn Smith OptionalView Answer on Stackoverflow
Solution 8 - FlutterANDYNVTView Answer on Stackoverflow
Solution 9 - FluttermrdevView Answer on Stackoverflow
Solution 10 - FlutterhedisamView Answer on Stackoverflow
Solution 11 - FlutterDenzil FerreiraView Answer on Stackoverflow
Solution 12 - FlutterMahmoud AlyView Answer on Stackoverflow
Solution 13 - FlutterGazihan AlankusView Answer on Stackoverflow
Solution 14 - FlutterPaloma BispoView Answer on Stackoverflow
Solution 15 - FlutterMatPagView Answer on Stackoverflow
Solution 16 - FlutterKernel JamesView Answer on Stackoverflow
Solution 17 - FlutterHammad PervezView Answer on Stackoverflow