TL;DR I have a RecyclerView
of EditText
s. 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 EditText
s. 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
.
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();
}
}
});
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.
In particular, if your RecyclerView is in a ScrollView but does not fill the screen, the ScrollView will not scroll (content fits in screen), and you will get the scroll UI in your RecyclerView (end of list effect when trying to scroll for example) even though it will not scroll when it gets bigger. Extending the LayoutManager really does the job.
After that when I scroll down or go up the view back to its normal position like the changes that I made it’s gone from view. It is because RecyclerView recycles every view which is not visible to the user. So, when the user scrolls back it recycles the previous view which is in normal form.
Instead of returning true, and therefore disabling all sorts of touch events, just return e.getAction () == MotionEvent.ACTION_MOVE; instead of return true; so only scroll/swipe events get cancelled. As setLayoutFrozen is deprecated, You can disable scrolling by freezing your RecyclerView by using suppressLayout.
So, when it is called we stored a flag value in our BokkModel class. Now when the user scrolls bottom or comes back to the previous position the view never changes. You can also add ClickListener on itemView when the user taps on the row you can change the background color and store in the model.
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;
}
RecyclerView will scroll to focused item. Try recyclerView.setFocusable(false). This worked for me.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With