RecycleView禁止滑动原理的分析、实现

需求:

有的时候在需要解决嵌套滑动冲突,需要禁止父View(也就是RecycleView)禁止滑动。

分析:

关于RecycleView的滑动,在RecycleView的源码中有这么一个函数:

		/**
         * Query if vertical scrolling is currently supported. The default implementation
         * returns false.
         *
         * @return True if this LayoutManager can scroll the current contents vertically
         */
        public boolean canScrollVertically() {
            return false;
        }

这个方法的意思是当前RecycleView是否能竖直方向滑动.但大家需要注意的是,这个方法是RecycleView的内部类LayoutManager里的一个方法,关于这个canScrollVertically方法,View类也有一个同名的方法。

	/**
     * Check if this view can be scrolled vertically in a certain direction.
     *
     * @param direction Negative to check scrolling up, positive to check scrolling down.
     * @return true if this view can be scrolled in the specified direction, false otherwise.
     */
    public boolean canScrollVertically(int direction) {
        final int offset = computeVerticalScrollOffset();
        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
        if (range == 0) return false;
        if (direction < 0) {
            return offset > 0;
        } else {
            return offset < range - 1;
        }
    }

RecycleView 里在判断是否可以上下滑动,调用的是LayoutManager类里的canScrollVertically方法,不是View下的。
例如:

mLayout.canScrollHorizontally()
mLayout.canScrollVertically()

其中mLayout就是我们在初始化RecycleView时传入的自己创建的LayoutManager对象。因此如果想通过自定义RecycleView 然后重写canScrollVertically方法显然是无效的,因为重写canScrollVertically方法是最终重写View类下的,不是LayoutManager类下的。

设计:

原理明白了,接下来就整理下解决问题的思路:
1、自定义LayoutManager,例如想要实现竖直方向滑动就是继承LinearLayoutManager类,然后重写canScrollVertically方法。
2、在这个自定义LayoutManager类中,暴露一个方法,方便外面将控制是否允许滑动的变量传入。
3、在自定义RecycleView 中暴露一个方法,方便调用者将控制是否允许滑动的变量传入。
4、在在自定义RecycleView获取调用者传入的变量值,然后获取当前
LayoutManager,并调用自定义LayoutManager暴露的方法。

实现(附源码):

1、自定义LayoutManager源码:

public class CofferLayoutManager extends LinearLayoutManager {

    /**
     * 是否允许滚动
     */
    private boolean mCanScroll = true;

    public CofferLayoutManager(Context context) {
        super(context);
    }

    public CofferLayoutManager(Context context, int orientation, boolean reverseLayout) {
        super(context, orientation, reverseLayout);
    }

    public CofferLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    public void setCanScroll(boolean canScroll){
        this.mCanScroll = canScroll;
    }

    @Override
    public boolean canScrollVertically() {
        if (!mCanScroll){
            return false;
        }
        return super.canScrollVertically();
    }
}

2、自定义RecycleView源码:

 */
public class CofferRecycleView extends RecyclerView {

    public CofferRecycleView(@NonNull Context context) {
        super(context);
    }

    public CofferRecycleView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public CofferRecycleView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public void setCanScrollVertically(boolean canScrollVertically){
        if (getLayoutManager() != null && getLayoutManager() instanceof CofferLayoutManager){
            ((CofferLayoutManager)getLayoutManager()).setCanScroll(canScrollVertically);
        }
    }
}

3、调用

// 允许滑动
mRecycleView.setCanScrollVertically(true);
// 禁止滑动
mRecycleView.setCanScrollVertically(false);

猜你喜欢

转载自blog.csdn.net/qq_26439323/article/details/106455200