Jordan Hall
Jordan Hall

Reputation: 371

Flutter how to get cursor in text field to stop moving to the beginning?

I have a text field in a flutter application that is designed to let the user edit data. When the TextField shows up it has the data already in it, which works fine. The problem is that when the user places the cursor at the end of the TextField, or anywhere inside it, and starts typing, the cursor moves back to the beginning and sometimes deletes the first word or two.

Ive tried putting the function calls to the controller inside of a setState, that didn't help. If i don't use a controller at all the problem goes away but then i can't save their input after they click outside of the box.

Here's the code for the text field and it's on Change

TextField(
    decoration: InputDecoration(
       border: InputBorder.none
    ),
    controller: controller,
    autofocus: true,
    onChanged: (text) {
       controller..text = text;
       controller..selection = TextSelection.collapsed(offset: controller.text.length);
    },
    maxLines: 8,

here's where I create the controller

 TextEditingController controller = new TextEditingController();
 controller.text = *initial text here*;

here's flutter doctor

[√] Flutter (Channel stable, v1.5.4-hotfix.2, on Microsoft Windows [Version 10.0.17134.829], locale en-US)
    • Flutter version 1.5.4-hotfix.2 at C:\Users\jhall\Desktop\flutter
    • Framework revision 7a4c33425d (9 weeks ago), 2019-04-29 11:05:24 -0700
    • Engine revision 52c7a1e849
    • Dart version 2.3.0 (build 2.3.0-dev.0.5 a1668566e5)

[√] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
    • Android SDK at C:\Users\jhall\AppData\Local\Android\sdk
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-Q, build-tools 28.0.3
    • Java binary at: C:\Program Files\Android\Android Studio1\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1343-b01)
    • All Android licenses accepted.
[√] Android Studio (version 3.4)
    • Android Studio at C:\Program Files\Android\Android Studio1
    • Flutter plugin version 35.3.1
    • Dart plugin version 183.6270
    • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1343-b01)
[√] VS Code, 64-bit edition (version 1.24.1)
    • VS Code at C:\Program Files\Microsoft VS Code
    • Flutter extension version 2.21.1
[√] Connected device (1 available)
    • Android SDK built for x86 • emulator-5554 • android-x86 • Android 9 (API 28) (emulator)
• No issues found!

So I basically just need the normal functionality you'd expect from a text entry field, for the user to be able to place the cursor wherever they'd like and type.

I've tried getting rid of the on Change all together and the problem persists.

Upvotes: 35

Views: 36970

Answers (5)

Tarun Sharma
Tarun Sharma

Reputation: 1008

TextField(
 enableInteractiveSelection: false
)

Setting this to true will enable features such as long-pressing the TextField to select text and show the cut/copy/paste menu, and tapping to move the text caret.

When this is false, the text selection cannot be adjusted by the user, text cannot be copied, and the user cannot paste into the text field from the clipboard.

Defaults to true.

Upvotes: 1

biniyam112
biniyam112

Reputation: 1172

Use this :

_controller.text = modifytext();
_controller.selection = TextSelection.fromPosition(TextPosition(offset: _controller.text.length));

Upvotes: 3

erluxman
erluxman

Reputation: 19385

You do not have to do

controller..text = text;

inside onChanged because the controller's text automatically changes once you connect it to TextField.

The reason is once you set some text to controller, it re-applies the text thus moving the cursor at front.

In your case :

TextField(
    decoration: InputDecoration(
       border: InputBorder.none
    ),
    controller: controller,
    autofocus: true,
    onChanged: (text) {},
    maxLines: 8,
)

should solve the issue.

Upvotes: 23

wz366
wz366

Reputation: 2930

You can capture cursor position before changing the text, then reapply cursor position to the new text:

onChanged: (text) {
       TextSelection previousSelection = controller.selection;
       controller.text = text;
       controller.selection = previousSelection;
    }

Upvotes: 14

LgFranco
LgFranco

Reputation: 1044

I think if you just remove the onChange from your code you'll get just what you need!

One thing that is important and may cause problems as well is that your controller must be set JUST ONCE! You can put it in the constructor of the state of your Widget or in the initState(). It'll be something like it:

import 'package:flutter/material.dart';

class MyStatefulPage extends StatefulWidget {
  @override
  State<MyStatefulPage> createState() {
    return _MyStatefulPageState();
  }
}
class _MyStatefulPageState extends State<MyStatefulPage> {

  TextEditingController controller;

  @override
  void initState() {
    super.initState();
    controller = new TextEditingController();
    controller.text = 'My Initial Text';
  } 

  @override
  Widget build(BuildContext context) {
    return TextField(
      decoration: InputDecoration(
       border: InputBorder.none
      ),
      controller: controller,
      autofocus: true,
      maxLines: 8,
    );
  }
}

Upvotes: 5

Related Questions