Reputation: 371
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
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
Reputation: 1172
Use this :
_controller.text = modifytext();
_controller.selection = TextSelection.fromPosition(TextPosition(offset: _controller.text.length));
Upvotes: 3
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
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
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