Nested RecyclerView. How to prevent parent RecyclerView from getting scrolled while child RecyclerView is scrolling?

前端 未结 14 1277
余生分开走
余生分开走 2020-12-07 21:24

I am trying to implement a horizontal recyclerview and each item of the recyclerview will be a vertical recyclerview with a grid layou

相关标签:
14条回答
  • 2020-12-07 21:42

    I fixed this issue in a similar project by taking the opposite approach to you (and everyone else here).

    Rather than allow the child to tell the parent when to stop looking at events, I let the parent decide when to ignore (based on direction). This approach requires a custom view though which can be a little more work. Below is what I created which would be used as the Outer/Parent view.

    public class DirectionalRecyclerView extends RecyclerView {
    
        private static float LOCK_DIRECTION_THRESHOLD; //The slop
        private float startX;
        private float startY;
        private LockDirection mLockDirection = null;
    
        public DirectionalRecyclerView(Context context) {
            super(context);
            findThreshold(context);
        }
    
        public DirectionalRecyclerView(Context context, AttributeSet attrs) {
            super(context, attrs);
            findThreshold(context)
        }
    
        public DirectionalRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            findThreshold(context);
        }
    
        private void findThreshold(Context context) {
            //last number is number of dp to move before deciding that's a direction not a tap, you might want to tweak it
            LOCK_DIRECTION_THRESHOLD = context.getResources().getDisplayMetrics().density * 12;
        }
    
        //events start at the top of the tree and then pass down to
        //each child view until they reach where they were initiated
        //unless the parent (this) method returns true for this visitor
        @Override
        public boolean onInterceptTouchEvent(MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    startX = event.getX();
                    startY = event.getY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (mLockDirection == null) {
                        float currentX = event.getX();
                        float currentY = event.getY();
                        float diffX = Math.abs(currentX - startX);
                        float diffY = Math.abs(currentY - startY);
                        if (diffX > LOCK_DIRECTION_THRESHOLD) {
                            mLockDirection = LockDirection.HORIZONTAL;
                        } else if (diffY > LOCK_DIRECTION_THRESHOLD) {
                            mLockDirection = LockDirection.VERTICAL;
                        }
                    } else {
                        //we have locked a direction, check whether we intercept
                        //the future touches in this event chain
                        //(returning true steals children's events, otherwise we'll
                        // just let the event trickle down to the child as usual)
                        return mLockDirection == LockDirection.HORIZONTAL;
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    mLockDirection = null;
                    break;
            }
            //dispatch cancel, clicks etc. normally
            return super.onInterceptTouchEvent(event);
        }
    
        private enum LockDirection {
            HORIZONTAL,
            VERTICAL
        }
    
    }
    
    0 讨论(0)
  • 2020-12-07 21:42

    Use this code to turn off scroll on recyclerview:

    recyclerView.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return true;
        }
    });
    
    0 讨论(0)
  • 2020-12-07 21:43

    The problem exists in Android's implementation of the onInterceptTouchEvent() method for RecyclerView. This blog calls out the problem and fixes it as well - http://nerds.headout.com/fix-horizontal-scrolling-in-your-android-app/. The only difference is that there the parent scrolls vertically and child horizontally. But the solution takes care that it should work for your situation as well.

    0 讨论(0)
  • 2020-12-07 21:44

    I used card view for cells and deactivated parent recycler view scrolling in child adapter with child cell itemView setOnClickListener.

    holder.itemView.setOnTouchListener { view, _ ->
        view.parent.parent.requestDisallowInterceptTouchEvent(true)
        false
    }
    

    we are calling view.parent.parent because of the fact that itemView is a cell layout and it's parent is our child recyclerView and also, we need to reach child recyclerView's parent to prevent parent recyclerView scrolling.

    0 讨论(0)
  • 2020-12-07 21:46

    You should do this way:

    innerRecyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
    
            @Override
            public void onTouchEvent(RecyclerView recycler, MotionEvent event) {
                // Handle on touch events here
                int action = event.getAction();
                switch (action) {
                    case MotionEvent.ACTION_DOWN:
    
                        recycler.getParent().requestDisallowInterceptTouchEvent(true);
    
                        break;
    
                    case MotionEvent.ACTION_UP:
    
                        recycler.getParent().requestDisallowInterceptTouchEvent(false);
    
                        break;
    
                    case MotionEvent.ACTION_MOVE:
    
                        recycler.getParent().requestDisallowInterceptTouchEvent(true);
    
                        break;
                }
    
    
            }
    
            @Override
            public boolean onInterceptTouchEvent(RecyclerView recycler, MotionEvent event) {
                return false;
            }
    
        });
    

    Hope this would help you.

    0 讨论(0)
  • 2020-12-07 21:50

    Now you can try android:nestedScrollingEnabled because Google fixed a crash with usages of nestedScrollingEnabled (Issue 197932)

    0 讨论(0)
提交回复
热议问题