终结计算RecyclerView的滑动距离问题
因项目需要,需要根据列表即时的滑动距离计算头部的透明度达到滑动改变透明度的效果。 但是通过几种常见的滑动距离计算方法都有坑所在,故评价并记录一下调研rv的滑动距离的几种方法;
首先,都是通过 RecyclerView#addOnScrollListener 的方法监听rv的滑动;
最常用的方法 dx,dy方法
通过定义一个全局变量,记录所有滑动的距离,比较阈值计算逻辑; 坑很多;如列表突变,长列表变短列表,无法知道滑动距离;
RecyclerView#computeHorizontalScrollOffset()
通过rv提供在竖直或者水平的范围内 计算滑动条偏移距离 来计算当前rv的滑动距离;不过局限是系统计算的是平均距离,所以只适用于高度或宽度相等的item情况下;
其他的方法要不过于复杂,要不就是有很多问题,下面提供下实测过后可用的其他解决方法:
computeVerticalScrollOffset 系列方法的组合使用
int offset = recyclerView.computeVerticalScrollOffset(); //当前滑动条在range中的偏移量
int extent = recyclerView.computeVerticalScrollExtent();// 计算滑动条的长度
int range = recyclerView.computeVerticalScrollRange();//计算滑动条的总共滑动范围range;
int percentage = (int)(100.0 * offset / (float)(range - extent));
//可计算当前rv的滑动百分比;
Log.i("RecyclerView, "scroll percentage: "+ percentage + "%");
通过滑动的百分比的方式提供切入点;
自定义LayoutManager,重写computeVerticalScrollOffset
网上提供的重写onLayoutCompleted方法,遍历容器中的child,按位置添加到map中是不对的,getchild获取到的是当前显示的childview,所以并不能获取到所有view的大小信息; 只需要重写computeVerticalScrollOffset,在这个方法中获取可见的itemview,添加到map中,在按照position计算当前滑动的距离即可;
class HomeOffsetLinearLayoutManager(context: Context) : LinearLayoutManager(context) {
private val heightMap: HashMap<Int, Int> = HashMap()
override fun computeVerticalScrollOffset(state: RecyclerView.State): Int {
return if (childCount == 0) {
0
} else try {
val firstVisiablePosition = findFirstVisibleItemPosition()
val firstVisiableView: View? = findViewByPosition(firstVisiablePosition)
if (firstVisiableView != null) {
heightMap.put(firstVisiablePosition,firstVisiableView.height)
var offsetY = -firstVisiableView.y.toInt()
for (i in 0 until firstVisiablePosition) {
offsetY += (if (heightMap[i] == null) 0 else heightMap[i])!!
}
offsetY
} else {
super.computeHorizontalScrollOffset(state)
}
} catch (e: Exception) {
super.computeHorizontalScrollOffset(state)
}
}
}
参考链接
版权声明:本文为MrJarvisDong原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。