item高度不同時(shí)Recyclerview獲取滑動(dòng)距離的方法
前言
最近遇到需求,要計(jì)算RecyclerView滑動(dòng)距離,用提供的computeVerticalScrollOffset()方法得到的值不是很準(zhǔn)確。是基于item的平均高度算得,如果列表中item高度一致可以用此方法。問題來了,我的應(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ì)列表已展示過的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è)可見item的position,通過heightMap循環(huán)累加0到positon的item高度,再加上第一個(gè)可見item不可見部分高度。最終得到整個(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 Canvas自定義實(shí)現(xiàn)時(shí)鐘效果
這篇文章主要為大家詳細(xì)介紹了Android Canvas自定義實(shí)現(xiàn)時(shí)鐘效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-12-12
Android開發(fā)之BottomSheetDialog組件的使用
BottomSheetDialog是底部操作控件,可在屏幕底部創(chuàng)建一個(gè)支持滑動(dòng)關(guān)閉視圖。本文將通過示例詳細(xì)講解它的使用,感興趣的小伙伴可以了解一下2023-01-01
Android仿簡(jiǎn)書長(zhǎng)按文章生成圖片效果
使用簡(jiǎn)書APP的同學(xué)都知道,簡(jiǎn)書有這樣一個(gè)功能;文章頁(yè)長(zhǎng)按內(nèi)容時(shí)底部會(huì)出現(xiàn)一個(gè) 生成圖片分享 的按鈕,點(diǎn)擊之后就可以將當(dāng)前的文章生成一張長(zhǎng)圖片;這張圖片可以保存到本地或分享給好友,同時(shí)還可為圖片設(shè)置成為白和黑兩種風(fēng)格,很有藝術(shù)范2017-03-03
ViewPager 與 Fragment相結(jié)合實(shí)現(xiàn)微信界面實(shí)例代碼
這篇文章主要介紹了ViewPager 與 Fragment相結(jié)合實(shí)現(xiàn)微信界面實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2016-07-07
Android開發(fā)DataBinding基礎(chǔ)使用
這篇文章主要為大家介紹了Android開發(fā)DataBinding基礎(chǔ)使用實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06

