Android Layout: Horizontal Recyclerview inside a Vertical Recyclerview inside a Viewpager with Scroll Behaviors

前端 未结 6 548
一整个雨季
一整个雨季 2020-11-30 20:33

This is the app I\'m trying to build with all the elements mapped out below:

Everything works, however, I want the inner horizontal recyclerview not to capt

相关标签:
6条回答
  • 2020-11-30 21:03

    I am a bit late but this will defintly work for others facing the same problem

     mRecyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
                @Override
                public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
                    int action = e.getAction();
                   // Toast.makeText(getActivity(),"HERE",Toast.LENGTH_SHORT).show();
                    switch (action) {
                        case MotionEvent.ACTION_POINTER_UP:
                            rv.getParent().requestDisallowInterceptTouchEvent(true);
    
                            break;
                    }
                    return false;
                }
    
    0 讨论(0)
  • 2020-11-30 21:17

    try

    public OuterRecyclerViewAdapter(List<Item> items) {
        //Constructor stuff
        viewPool = new RecyclerView.RecycledViewPool();
    }
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //Create viewHolder etc
        holder.innerRecyclerView.setRecycledViewPool(viewPool);
    
    }
    

    inner recylerview will use the same viewpool and it'll be smoother

    0 讨论(0)
  • 2020-11-30 21:18

    Tested solution:

    All you need is to call mInnerRecycler.setNestedScrollingEnabled(false); on your inner RecyclerViews


    Explanation:

    RecyclerView has support for nested scrolling introduced in API 21 through implementing the NestedScrollingChild interface. This is a valuable feature when you have a scrolling view inside another one that scrolls in the same direction and you want to scroll the inner View only when focused.

    In any case, RecyclerView by default calls RecyclerView.setNestedScrollingEnabled(true); on itself when initializing. Now, back to the problem, since both of your RecyclerViews are within the same ViewPager that has the AppBarBehavior, the CoordinateLayout has to decide which scroll to respond to when you scroll from your inner RecyclerView; when your inner RecyclerView's nested scrolling is enabled, it gets the scrolling focus and the CoordinateLayout will choose to respond to its scrolling over the outer RecyclerView's scrolling. The thing is that, since your inner RecyclerViews don't scroll vertically, there is no vertical scroll change (from the CoordinateLayout's point of view), and if there is no change, the AppBarLayout doesn't change either.

    In your case, because your inner RecyclerViews are scrolling in a different direction, you can disable it, thus causing the CoordinateLayout to disregard its scrolling and respond to the outer RecyclerView's scrolling.


    Notice:

    The xml attribute android:nestedScrollingEnabled="boolean" is not intended for use with the RecyclerView, and an attempt to use android:nestedScrollingEnabled="false" will result in a java.lang.NullPointerException so, at least for now, you will have to do it in code.

    0 讨论(0)
  • 2020-11-30 21:18

    if any one still looking , try this :

    private val Y_BUFFER = 10
    private var preX = 0f
    private var preY = 0f
    
    mView.rv.addOnItemTouchListener(object : RecyclerView.OnItemTouchListener {
            override fun onTouchEvent(p0: RecyclerView, p1: MotionEvent) {
    
                }
    
            override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
                    when (e.action) {
                        MotionEvent.ACTION_DOWN -> rv.parent.requestDisallowInterceptTouchEvent(true)
                        MotionEvent.ACTION_MOVE -> {
                            if (Math.abs(e.x - preX) > Math.abs(e.y - preY)) {
                                rv.parent.requestDisallowInterceptTouchEvent(true)
                            } else if (Math.abs(e.y - preY) > Y_BUFFER) {
                                rv.parent.requestDisallowInterceptTouchEvent(false)
                            }
    
                        }
                    }
                    preX = e.x
                    preY = e.y
                    return false
                }
    
                override fun onRequestDisallowInterceptTouchEvent(p0: Boolean) {
                }
            })
    

    it checks if currently scrolling horizontal then don't allow parent to handel event

    0 讨论(0)
  • 2020-11-30 21:19

    I would suggest you add the horizontal recyclerview inside fragments like the google app

    0 讨论(0)
  • 2020-11-30 21:20

    Tested solution, use a custom NestedScrollView().

    Code:

    public class CustomNestedScrollView extends NestedScrollView {
        public CustomNestedScrollView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            if (ev.getAction() == MotionEvent.ACTION_DOWN) {
             // Explicitly call computeScroll() to make the Scroller compute itself
                computeScroll();
            }
            return super.onInterceptTouchEvent(ev);
        }
    }
    
    0 讨论(0)
提交回复
热议问题