Flutter开发问题:TextFormField光标自动跳至开头,需定位至文本末尾
Hey there! I see you're dealing with that annoying issue where tapping your TextFormField makes the cursor jump to the start instead of staying at the end of existing text. Let's get this sorted out quickly.
The Root Cause
This happens because when the field gains focus, Flutter's default behavior doesn't always position the cursor at the end of pre-filled text. We need to manually override this by setting the cursor position explicitly when the field is focused.
Solution 1: Using a FocusNode (Recommended)
This approach gives you more control over focus state and works reliably:
- First, create a
FocusNodein your state class:
FocusNode _titleFocusNode = FocusNode();
- Add a listener to the FocusNode in
initStateto set the cursor position when the field gains focus:
@override void initState() { super.initState(); _titleFocusNode.addListener(() { if (_titleFocusNode.hasFocus) { // Move cursor to the end of the text titleContr.selection = TextSelection.fromPosition( TextPosition(offset: titleContr.text.length) ); } }); }
- Attach the FocusNode to your TextFormField, and don't forget to dispose it later:
Padding( padding: EdgeInsets.only(top: 15.0, bottom: 15.0), child: TextFormField( controller: titleContr, focusNode: _titleFocusNode, // Add this line style: textStyle, validator: (String value) { if (value.isEmpty) { return 'Please enter a title'; } }, decoration: InputDecoration( labelText: 'Title', labelStyle: textStyle, hintText: 'Add a title for the Task', border: OutlineInputBorder( borderRadius: BorderRadius.circular(5.0) ) ), ), )
- Dispose the FocusNode and TextEditingController in
disposeto prevent memory leaks:
@override void dispose() { _titleFocusNode.dispose(); titleContr.dispose(); super.dispose(); }
Solution 2: Quick Fix with onTap Callback
If you want a simpler, one-off solution without a FocusNode, you can use the onTap callback with addPostFrameCallback (this ensures we override Flutter's default cursor positioning):
Padding( padding: EdgeInsets.only(top: 15.0, bottom: 15.0), child: TextFormField( controller: titleContr, style: textStyle, onTap: () { WidgetsBinding.instance.addPostFrameCallback((_) { titleContr.selection = TextSelection.fromPosition( TextPosition(offset: titleContr.text.length) ); }); }, validator: (String value) { if (value.isEmpty) { return 'Please enter a title'; } }, decoration: InputDecoration( labelText: 'Title', labelStyle: textStyle, hintText: 'Add a title for the Task', border: OutlineInputBorder( borderRadius: BorderRadius.circular(5.0) ) ), ), )
Either of these solutions will make sure the cursor stays at the end of your existing text when you tap the field. Test it out, and it should work like a charm!
内容的提问来源于stack exchange,提问作者R. Gurung

