I have a CustomScrollView
with a SliverAppBar
that hides on scroll.
On the app bar is a search button that, when pressed, puts a TextField
into the app bar.
When the field gets focus, it causes the scroll view to scroll all the way to the top, and the app bar gets stuck up in the "unsafe" area:
The Scaffold docs mention that when the keyboard is shown the scaffold's insets change and the scaffold is rebuilt, causing the "focused widget will be scrolled into view if it's within a scrollable container".
This seems like the behavior I don't want. I looked but couldn't understand the mechanism or how to suppress it. Is doing so possible?
The source code for the view in the image is here.
Also I note that this problem didn't happen in my previous implementation with non-sliver, standard widgets. I suspect this is because the app bar was not in a scrollable view, whereas SliverAppBar
is inside the CustomScrollView
so that it can interact with the main body.
Edit: This issue was fixed by this PR which appears to have first landed in Flutter 1.22.0.
It took some sleuthing, but I eventually found the mechanism for this behavior.
TextField
wraps EditableText
. When the latter gains focus, it will invoke _showCaretOnScreen
, which includes a call to renderEditable.showOnScreen
. This bubbles up and eventually causes the scrolling behavior.
We can force _showCaretOnScreen
to return early here if we supply to the TextField
a hacked ScrollController
that always returns false
from hasClients
:
class _HackScrollController extends ScrollController {
// Causes early return from EditableText._showCaretOnScreen, preventing focus
// gain from making the CustomScrollView jump to the top.
@override
bool get hasClients => false;
}
The behavior does not seem intentional, so I reported it as bug #60422.
This workaround may not be very stable.
I don't know what adverse effects the hasClients
override might have.
The docs for TextField
say that the scrollController
is used "when vertically scrolling the input". In this use case we don't want vertical scrolling anyway, so the workaround might not cause any problems. In my brief testing it didn't seem to cause problems with horizontal (overflow) scrolling.