I have a simple input form; it\'s a vertical LinearLayout with EditTexts inside a ScrollView.
I tried all solutions posted here but either didn't work on certain Android versions or it messed up with some other behavior like when switching between touch and non-touch mode (when you click buttons or use the trackpad).
I finally found that overriding the method getFocusables
did the trick:
public class FixedFocusScrollView extends ScrollView {
public FixedFocusScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public FixedFocusScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FixedFocusScrollView(Context context) {
super(context);
}
@Override
public ArrayList<View> getFocusables(int direction) {
return new ArrayList<View>();
}
}
Just thought I'd share my solution to this. Even though some of the other answer's comments state that you cannot override this behavior, that is not true. This behavior stops as soon as you override the onRequestFocusInDescendants()
method. So simply create your ScrollView extension to do this:
public class NonFocusingScrollView extends ScrollView {
public NonFocusingScrollView(Context context) {
super(context);
}
public NonFocusingScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public NonFocusingScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
return true;
}
}
And you're done. The ScrollView
will mess with your focus no more.
I have had such a problem too. The only way that helped me is to extend scroll view and to override neigher
@Override
public ArrayList<View> getFocusables(int direction) {
return new ArrayList<View>();
}
or
@Override
protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
return true;
}
but to override ViewGroup.requestChildFocus(View child, View focused)
method as following:
@Override
public void requestChildFocus(View child, View focused) {
// avoid scrolling to focused view
// super.requestChildFocus(child, focused);
}
What worked for me was combining @dmon's and @waj's answers.
Only overriding onRequestFocusInDescendants()
worked great when I was only dealing with EditTexts inside of the ScrollView, but when I started added multiple View types, it didn't work so well.
Only overriding getFocusables()
did not work at all.
Overriding both onRequestFocusInDescendants()
AND getFocusables()
seems to work beautifully in all scenarios.
public class FixedFocusScrollView extends ScrollView {
public FixedFocusScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public FixedFocusScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FixedFocusScrollView(Context context) {
super(context);
}
@Override
public ArrayList<View> getFocusables(int direction) {
return new ArrayList<View>();
}
@Override
protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
return true;
}
}
This solved the issue for me. It may not be applicable in all situations, but works well for mine where the scrolling is done programmatically:
View originalFocus = getCurrentFocus();
scroller.fullScroll(View.FOCUS_DOWN);
if (originalFocus!=null) {originalFocus.requestFocusFromTouch();}
For such behavior use nextFocusUp and nextFocusDown.
<EditText
android:id="@+id/my_edit_text"
android:nextFocusDown="@id/my_edit_text"
android:nextFocusUp="@id/my_edit_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</EditText>