item高度不同時(shí)Recyclerview獲取滑動(dòng)距離的方法
前言
最近遇到需求,要計(jì)算RecyclerView滑動(dòng)距離,用提供的computeVerticalScrollOffset()方法得到的值不是很準(zhǔn)確。是基于item的平均高度算得,如果列表中item高度一致可以用此方法。問(wèn)題來(lái)了,我的應(yīng)用場(chǎng)景是各item高度不一,這時(shí)就只能另找方法了。
方法一:
網(wǎng)上找的方法,用一個(gè)變量去統(tǒng)計(jì),每次滑動(dòng)的時(shí)候累加y軸偏移量。item插入\移動(dòng)\刪除的時(shí)候,需要手動(dòng)去更新totalDy,不然就會(huì)一直錯(cuò)下去。
private int totalDy = 0;
mRecycler.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerview, int dx, int dy) {
totalDy -= dy;
}
}
方法二:
方法一比較麻煩,而且坑較多。所以考慮重寫LinearLayoutManager的computeVerticalScrollOffset()方法,既然原生方法是按平均高度計(jì)算的,那重寫該計(jì)算邏輯,就能達(dá)到我們想要的效果。
1.統(tǒng)計(jì)列表已展示過(guò)的item的高度,在每次布局完成的時(shí)候,用一個(gè)map記錄positon位置item對(duì)應(yīng)的view的高度。
private Map<Integer, Integer> heightMap = new HashMap<>();
int count = getChildCount();
for (int i = 0; i < count; i++) {
View view = getChildAt(i);
heightMap.put(i, view.getHeight());
}
2.重寫computeVerticalScrollOffset(),找到當(dāng)前屏幕第一個(gè)可見(jiàn)item的position,通過(guò)heightMap循環(huán)累加0到positon的item高度,再加上第一個(gè)可見(jiàn)item不可見(jiàn)部分高度。最終得到整個(gè)列表的滑動(dòng)偏移。
@Override
public int computeVerticalScrollOffset(RecyclerView.State state) {
if (getChildCount() == 0) {
return 0;
}
int firstVisiablePosition = findFirstVisibleItemPosition();
View firstVisiableView = findViewByPosition(firstVisiablePosition);
int offsetY = -(int) (firstVisiableView.getY());
for (int i = 0; i < firstVisiablePosition; i++) {
offsetY += heightMap.get(i) == null ? 0 : heightMap.get(i);
}
return offsetY;
}
3.最終代碼
public class OffsetLinearLayoutManager extends LinearLayoutManager {
public OffsetLinearLayoutManager(Context context) {
super(context);
}
private Map<Integer, Integer> heightMap = new HashMap<>();
@Override
public void onLayoutCompleted(RecyclerView.State state) {
super.onLayoutCompleted(state);
int count = getChildCount();
for (int i = 0; i < count ; i++) {
View view = getChildAt(i);
heightMap.put(i, view.getHeight());
}
}
@Override
public int computeVerticalScrollOffset(RecyclerView.State state) {
if (getChildCount() == 0) {
return 0;
}
try {
int firstVisiablePosition = findFirstVisibleItemPosition();
View firstVisiableView = findViewByPosition(firstVisiablePosition);
int offsetY = -(int) (firstVisiableView.getY());
for (int i = 0; i < firstVisiablePosition; i++) {
offsetY += heightMap.get(i) == null ? 0 : heightMap.get(i);
}
return offsetY;
} catch (Exception e) {
return 0;
}
}
}
mRecycler.setLayoutManager(new OffsetLinearLayoutManager(mContext));
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
android實(shí)現(xiàn)獲取正在運(yùn)行的應(yīng)用程序
android如何獲取正在運(yùn)行的應(yīng)用程序,因?yàn)樵趂ramework中想添加這個(gè)功能,所以寫了個(gè)appliction來(lái)實(shí)現(xiàn)一下獲取正在運(yùn)行的應(yīng)用程序2013-01-01
Android實(shí)現(xiàn)通話自動(dòng)錄音
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)通話自動(dòng)錄音,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-10-10
Android 一個(gè)日歷控件的實(shí)現(xiàn)代碼
本篇文章主要介紹了Android 一個(gè)日歷控件的實(shí)現(xiàn)代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-05-05
Android WebView如何判定網(wǎng)頁(yè)加載的錯(cuò)誤
這篇文章主要介紹了Android WebView如何判定網(wǎng)頁(yè)加載的錯(cuò)誤,幫助大家更好的理解和學(xué)習(xí)使用Android,感興趣的朋友可以了解下2021-04-04
Android Studio 超級(jí)簡(jiǎn)單的打包生成apk的方法
本篇文章主要介紹了Android Studio 超級(jí)簡(jiǎn)單的打包生成apk的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10
自定義toast外形,多次點(diǎn)擊不會(huì)總是彈出toast的實(shí)現(xiàn)方法
下面小編就為大家?guī)?lái)一篇自定義toast外形,多次點(diǎn)擊不會(huì)總是彈出toast的實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04
Android.mk文件中添加第三方j(luò)ar文件的方法
這篇文章主要介紹了Android.mk文件中添加第三方j(luò)ar文件及引用第三方j(luò)ar包的方法,需要的朋友可以參考下2018-01-01
ViewPager 滑動(dòng)一半的判斷方法以及左滑右滑判斷實(shí)例
下面小編就為大家?guī)?lái)一篇ViewPager 滑動(dòng)一半的判斷方法以及左滑右滑判斷實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04

