Seems to be a common problem without a great solution that I have found. Goal is to stop a ScrollView
from auto-scrolling to an EditText
(or any view for that matter) that has focus.
You have a bunch of views (Button
s, TextView
s, etc) in an ScrollView
, one of which is an EditText
. Upon clicking say a Button within the ScrollView
, the ScrollView
scrolls down to the EditText
(its off screen). This is not desired, as there are other elements that you don't want scrolled off the screen.
Now I can stop this from happening when the screen first shows by having other focusable elements in the ScrollView
. However, the general problem still exists. The user scrolls down manually to the EditText
, enters some numbers, then scrolls up to the top (EditText
off screen now), they click a button in the ScrollView
, and guess what? The ScrollView
scrolls down to that darn EditText
.
I'm thinking about extending the ScrollView
and overriding some of the methods there like findFocusableViewInBounds
, but I have a feeling I'll just be getting myself into more trouble.
Please help if you can.
I've played around with things like having an 0 height EditText
at the top of my ScrollView
, adding Next Focusable element properties to the other items in the ScrollView
, etc. I suppose one "hack" might be to get the EditText
to lose focus when the virtual or manual keyboard gets hidden or something.
My solution is below, to trace the source code and override some function to stop auto scrolling by focused item.
You can check if the
focusedView
is TextView or its child is TextView, by usingfocusedView.findViewById(R.id.textview_id_you_defined) != null
orfocusedView instanceof TextView == true
.We can write a custom ScrollView and override the onScrollChanged method and clear the focus from the focused view and optionally hide the keyboard.
I had the same problem. There's one trick that I'm using to deal with this problem:
Create a custom ScrollView (create a class and have it extend HorizontalScrollView) and make a getter setter for scrollable. Then override computeScrollDeltaToGetChildRectOnScreen.
How it works: Every time android has an edit text or something in focus that is off screen it calls method computeScrollDeltaToGetChildRectOnScreen to bring it into view. If you Override it and return 0 when it is disabled than it will not scroll...
So you will have A custom scroll view like this:
You can use this inside your XML like this:
After struggling with that problem for quite some time, I've found a solution that seems to work without being too ugly. First, make sure that whatever
ViewGroup
(directly) contains yourEditText
hasdescendantFocusability
set to "Before Descendants,"focusable
set to "true" andfocusableInTouchMode
set to "true." This will not be theScrollView
itself, but the layout inside where you have your various views. Next add anonTouchListener
to yourScrollView
that removes focus from theEditText
whenever it is touched, like so:Tell me if that doesn't fix it. What should happen is that the Layout gets focus instead of the
EditText
, so no scrolling should happen.Here is what I did
The reason is in such cases you have to make all other views focus-able inside the scrollview by an explicit
android:focusable="true"
and then<requestFocus></requestFocus>
. This should work everytime IMO