需求:
有的时候在需要解决嵌套滑动冲突,需要禁止父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);