I have a TextField
that I set to readonly
, and it contains a TextEditingController
. When I set the text on the controller through code, I want the text field to jump all the way to the back.
TextField(
readOnly: true,
controller: _dialogStore.exportFolderPathController,
),
The store in this case is part of mobx, which I use instead of stateful widgets. But that doesn't matter for the question here.
I have a rather small text box. So when the text is long I want the text field to scroll all the way to the end. When I set the text on the scroll controller via exportFolderPathController.selection = TextSelection.collapsed(offset: exportFolderPathController.text.length);
, it doesn't want to update, but when I set readonly
to false
, it does work.
I have been digging through the code and found hints of if(readonly)
, for showing the selection handlers.
Eventually I got it to work with a dirty bool
and a Future.delayed
solution like so:
Future<void> setFilePath(String filePath) async {
_readonly = false;
exportFolderPathController.text = filePath;
exportFolderPathController.selection =
TextSelection.collapsed(offset: exportFolderPathController.text.length);
// wait for the scroll animation to finish
await Future.delayed(const Duration(milliseconds: 300));
_readonly = true;
}
I really don't like the Future.delayed
here, since it's an assumtion that it will take a while for the animation to finish. What are my alternatives?
I saw that there is also the possibility to add a ScrollController
, but I couldn't get that to work.
The quickest and easiest solution is below
Initialize a scrollController
final ScrollController _scrollController = ScrollController();
Then assign that controller in TextField
TextField(
readOnly: true,
controller: _dialogStore.exportFolderPathController,
scrollController: _scrollController,
)
Last step is to add 2 lines in your setFilePath()
method
Future<void> setFilePath(String filePath) async {
WidgetsBinding.instance.addPostFrameCallback((_) {
final scrollOffset = _scrollController.position.maxScrollExtent;
_scrollController.jumpTo(scrollOffset);
});
}
call above method in initState.
And you're done. You'll achieve what you want.