16

TL;DR I have a RecyclerView of EditTexts. When the user is focused on EditText #1 and taps on EditText #2, I want EditText #2 to get focus but I don't want the ReyclerView to scroll. How can I achieve this?


I'm trying to work with a RecyclerView populated with a bunch of EditTexts. When I'm focused on one EditText and I click on another, the RecyclerView scrolls so that the second is at the top of the screen. I want to disable this auto-scrolling from the RecyclerView, but I still want the user to be able to scroll, and I still want the second EditText to be focused on so the user can start typing. How can I achieve this?

I've already tried the following solutions:

  • https://stackoverflow.com/a/8101614/4077294, but with a RecyclerView.OnItemTouchListener. I called recyclerView.requestFocusFromTouch in onInterceptTouchEvent.

    • Behavior: Scrolled to the top of the tapped EditText all the time.
  • Clearing the focus from any EditText whenever it was focused on, via

    editText.setOnFocusChangeListener(new OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, bool hasFocus) {
            if (hasFocus) {
                v.clearFocus();
            }
        }
    });
    
    • Behavior: The keyboard never showed up, and the RecyclerView still scrolled to the top.

Disabling scrolling altogether as in this question is not acceptable because I still want the user to be able to scroll.

James Ko
  • 32,215
  • 30
  • 128
  • 239
  • Try this : android:windowSoftInputMode="adjustNothing|stateHidden" in manifest – Sarthak Gandhi Jul 09 '17 at 05:32
  • Can you please post what worked for you? I'm also interested in knowing. – HB. Jul 09 '17 at 05:59
  • @HBrooks There hasn't been an answer yet. – James Ko Jul 09 '17 at 07:51
  • 2
    see `requestChildRectangleOnScreen` you can override it either at view or layout manager level – pskink Jul 09 '17 at 14:28
  • @pskink Can you give an example of how I would use it? – James Ko Jul 09 '17 at 14:32
  • https://pastebin.com/8JLSMkF7 – pskink Jul 09 '17 at 14:43
  • @pskink Thanks. I'll try what you've posted when I'm able to work on my app again, and let you know if it works. – James Ko Jul 10 '17 at 12:29
  • the longer version (with rect intersection checks) is for cases when you could navigate your `RV` using the D-pad, so you could just start with the shorter one (only returning false) – pskink Jul 10 '17 at 12:34
  • @pskink Thank you so much. I tried your solution with just returning false, and it worked perfectly. If you'd like to post that as an answer, I'll accept it. – James Ko Jul 11 '17 at 01:01
  • but remember when using the short form (just return false) if you use arrow keys (dpad, hardware keyboard and some soft keyboards also have arrows) you can simply lose your cursor and go outside the bounds of your `RV` - thats why the form with some checks could be better – pskink Jul 11 '17 at 06:49
  • @pskink Oh, I didn't realize that. Will make a note to come back to this question. Thanks! – James Ko Jul 11 '17 at 12:34

2 Answers2

33

I ended up with this solution from @pskink:

recylerView.setLayoutManager(new LinearLayoutManager(this) {
    @Override
    public boolean requestChildRectangleOnScreen(RecyclerView parent, View child, Rect rect, boolean immediate) {
        return false;
    }
});

It seems to work perfectly, but @pskink has mentioned that this could have problems when using arrow keys. He's posted another solution here: https://pastebin.com/8JLSMkF7. If you have problems with the above solution, you may try the alternative solution at the link. For now, I'm sticking with the one I just posted here.

UPDATE

Since support-library v25.3.0 you should also override another requestChildRectangleOnScreen method in LayoutManager:

@Override
public boolean requestChildRectangleOnScreen(RecyclerView parent, View child, Rect rect, boolean immediate, boolean focusedChildVisible) {
    return false;
}
Sergei Vasilenko
  • 2,313
  • 2
  • 27
  • 38
James Ko
  • 32,215
  • 30
  • 128
  • 239
2

RecyclerView will scroll to focused item. Try recyclerView.setFocusable(false). This worked for me.