前几日在某机型上线上出现了一个与RecyclerView
上划下滑相关的BUG
。
源码解读
看了会儿RecyclerView
的canScrollVertically(int direction)
函数:
/**
* 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;
}
}
注释:入参direction
为负数时检测向上滑(手势由下往上,getScrollY()
减少),为正时检测向下滑(手势由上往下,getScrollY()
增加)。
Function解读
computeVerticalScrollOffset
表示当前View已经上滑的高度(View
顶部到View
内容顶部的高度差)computeVerticalScrollExtent
表示当前View的显示区域高度computeVerticalScrollRange
表示整个View控件内容的高度
- 当
Offset > 0
则可以下滑(手势由上往下) Offset + Extent < Range
则可以上滑(此处的Range
表示computeVerticalScrollRange
)- 当
Offset + Extent = Range
则已到达内容顶部,无法继续上滑(手势由下往上)
技术杂记
NestedScrollView+RecyclerView 滑动卡顿简单解决方案
在NestedScrollView
嵌套RecyclerView
<android.support.v4.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/linerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
NestedScrollView
中包含了LinearLayout
,LinearLayout
包含了一系列的组件,其中包括RecyclerView
,RecyclerView
和NestedScrollView
都有滚动事件,这种情况下进行滑动操作,fling
的操作体验很差,失去惯性。
为了提高fling
的体验,对<RecyclerView/>
的属性进行改动,添加:
android:nestedScrollingEnabled="false"
这里设置为false,放弃自己的滑动,交给外部的NestedScrollView处理,就没有出现卡顿的现象了,并且有fling的效果
文档说明:
Enable or disable nested scrolling for this view.
If this property is set to true the view will be permitted to initiate nested scrolling operations with a compatible parent view in the current hierarchy. If this view does not implement nested scrolling this will have no effect. Disabling nested scrolling while a nested scroll is in progress has the effect of stopping the nested scroll.
修改后的文件:
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:nestedScrollingEnabled="false" />