前言
最近笔者遇到了关于获取listview与recyclerview滑动高度的需求,recyclerview提供了相应的方法,listview没有提供直接可以使用的方法,百度搜到的也只是获取一个大概距离,后来recyclerview由于item的高度改变,遇到了相似的问题,最后用相似的方法解决,记录一下
一、Listview
首先看listview提供了什么方法,他的scrolllistener有一个方法:
// firstVisibleItem 为首个可见的item的位置
//visibleItemCount 为屏幕里可见的item的数目
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
这里再解释一下firstVisibleItem, 我们知道listview是有复用回收的,被回收的就会从listview中移出,所以firstVisibleItem为第一个可见项的下标。可以总结为:
此时listview的第一个childview的下标就是firstVisibleItem
即: listView.getChildAt(0)获取到的view在你的adapter的数据中顺序为第firstVisibleItem。
那么该怎么判断滑动值呢,我们可以通过这个获取到的view与下标值firstVisibleItem进行操作。view可以直接获取其weight,同时我们知道view.getTop为其在其顶部父view的位置。
那么该怎么判断listview滑动值呢,我们按照下标值区分
当firstVisibleItem为0时,说明当前界面展示的第一个就是所有item的第一个,那么滑动值就是其top,所以有 滑动值 = view.getTop
同时我们可以将我们第一个view的高度存起来
当firstVisibleItem为6时(这里拿6做例子),说明当前界面展示的第一个就是所有item的第七个,此时滑动值应该为前面6个item的高度和+第七个item的getTop值。那么前6个item的高度怎么得到呢?刚刚说了可以通过view.getHeight获取其高度并且存起来,就在这里了。
代码:
var heights = MutableList(10) {
return@MutableList 0;
}
listView.setOnScrollListener(object : OnScrollListener {
override fun onScrollStateChanged(view: AbsListView?, scrollState: Int) {
}
override fun onScroll(
view: AbsListView,
firstVisibleItem: Int,
visibleItemCount: Int,
totalItemCount: Int
) {
val view = view.getChildAt(0);
if (view == null) {
//有可能没有数据,所以返回
return
}
var scrollHeight = 0;
if (firstVisibleItem == 0) {
heights[firstVisibleItem] = view.height;
scrollHeight = view.top;
} else {
heights[firstVisibleItem] = heights[firstVisibleItem - 1] + view.height;
//由于是向上滑动,那么top是负数
scrollHeight = heights[firstVisibleItem - 1] + view.top*-1;
}
Log.e("滑动距离", scrollHeight.toString());
}
})
二、recyclerView
recyclerView本身提供了方法:
//dy即为本次滑动相对于上次滑动的偏移值
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy){}
我们可以设置一个变量对dy进行累加,就可以得到滑动值。
但是既然提到Recyclerview,就肯定还有更进一步的,也是本次写这个文章的原因之一。本次作者的需求是: 外部有一个背景值,随着滑动距离变化,但是在滑动时,前面的view有可能改变高度(此时dy并不会刷新),这样就会出现还没滑动到最顶部,背景值就变成滑动到最顶端才会出现的颜色。
那我们就可以采取和listview相似的方式,实时获取到显示的第一个的高度,然后这样进行刷新。ListView告诉我们当前显示的第一个view的position,那Recyclerview怎么做呢:
//获取到此时在屏幕上的第一个view
val view = recyclerView.getChildAt(0);
//poiton即为该view在所有view中的位置
val position =recyclerView.getChildAdapterPosition(view)
其他的流程就和listview一样了
总结
写博客怎么这么久呀,呜呜呜