Android獲取RecyclerView滑動(dòng)距離方法詳細(xì)講解
先說(shuō)能用的究極解決方案,大家著急的直接復(fù)制走,以后想了解再過(guò)來(lái)看
沒(méi)有header,且所有Item的高度一致
private fun getScrollYDistance(recyclerView: RecyclerView): Int? {
kotlin.runCatching {
val layoutManager = recyclerView.layoutManager as LinearLayoutManager
val position = layoutManager.findFirstVisibleItemPosition()
val firstVisibleChildView = layoutManager.findViewByPosition(position)
val itemHeight = firstVisibleChildView!!.height
return position * itemHeight - firstVisibleChildView.top
}
return null
}有一個(gè)header,其他所有Item高度一致
var headerHeight = 0
private fun getScrollYDistance(recyclerView: RecyclerView): Int? {
kotlin.runCatching {
val layoutManager = recyclerView.layoutManager as LinearLayoutManager
val position = layoutManager.findFirstVisibleItemPosition()
if (position == 0) {
val headerView = layoutManager.findViewByPosition(0)
headerHeight = headerView!!.height
}
val firstVisibleChildView = layoutManager.findViewByPosition(position)
val itemHeight = firstVisibleChildView!!.height
return if (position == 0) {
position * itemHeight - firstVisibleChildView.top
} else {
(position - 1) * itemHeight - firstVisibleChildView.top + headerHeight
}
}
return null
}有多個(gè)header,其他Item一致
Integer[] headerHeightArray;
private int getScollYDistance(){
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getRecyclerView().getLayoutManager();
// 獲取第一個(gè)可見item的位置
int position = layoutManager.findFirstVisibleItemPosition();
// 獲取第一個(gè)可見item
View firstVisiableChildView = layoutManager.findViewByPosition(position);
// 必須考慮有沒(méi)有Header 預(yù)存下所有header的高度
int headerCount = adapter.getHeaderCount();
if (headerCount > 0) {
if (headerHeightArray == null) {
headerHeightArray = new Integer[headerCount];
}
if (position < headerCount) {
View headerView_i = layoutManager.findViewByPosition(position);
headerHeightArray[position] = headerView_i.getHeight();
}
}
// 獲取第一個(gè)可見item的高度
int itemHeight = firstVisiableChildView.getHeight();
// 獲取第一個(gè)可見item的位置
int distance = 0;
if (position == 0) {
distance = position * itemHeight - firstVisiableChildView.getTop();
} else {
int allHeaderHeight = 0;
for (int i = 0; i < Math.min(position,headerCount); i++) {
allHeaderHeight = allHeaderHeight + headerHeightArray[i];
}
distance = (position - Math.min(position,headerCount)) * itemHeight - firstVisiableChildView.getTop() + allHeaderHeight;
}
return distance;
}注意調(diào)用位置:
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
getScollYDistance();
}
});試過(guò)的一些想法,都有一些問(wèn)題,有的可以彌補(bǔ),有的直接玩完
RecyclerView 雖然有g(shù)etScrollX() 和 getScrollY(), 但是測(cè)試發(fā)現(xiàn)這兩個(gè)函數(shù)總是返回0,太無(wú)語(yǔ)了。因此想到了下面幾種方法來(lái)實(shí)現(xiàn)獲取滑動(dòng)距離:
利用OnScrollListener
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
private int totalDy = ;
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
totalDy -= dy;
}
});如代碼所述,totalDy的確保存了 RecyclerView 的滑動(dòng)距離,但是當(dāng)我向下滑動(dòng) RecyclerView ,之后插入/刪除/移動(dòng) Item 的時(shí)候,totalDy 就變得不精確了;比如刪除或者插入新的Item,那么totalDy就不能再回歸到 0了。這個(gè)可以通過(guò)當(dāng)刪除或者插入時(shí)來(lái)對(duì)totalDy進(jìn)行加減相應(yīng)的高度。
totalDy = recyclerView.computeVerticalScrollOffset();
然而compute方法計(jì)算出的并不是滑動(dòng)的精確距離,stackOverflow上有答案解釋其為 item 的平均高度 * 可見 item 數(shù)目,不是我們需要的精確距離。
totalDy = recyclerView.getChildAt().getTop();
依靠第一個(gè)item的滑動(dòng)距離來(lái)進(jìn)行動(dòng)畫的設(shè)置,但是根據(jù)該方法得出的 totalDy 在滑動(dòng)到一定程度后清零。
這是因?yàn)閞ecyclerViewl.getChildAt(0) 返回的永遠(yuǎn)是第一個(gè)可見的child,不是所有view list 的第一個(gè)child,因此這種用法是得不到滑動(dòng)距離的。
另外下面這三種用法都是等價(jià)的,都是獲取第一個(gè)可見的child:
LinearLayoutManager layoutManager = (LinearLayoutManager) this.getLayoutManager();
View firstVisiableChildView = this.getChildAt();
View firstVisiableChildView = layoutManager.getChildAt()
int position = layoutManager.findFirstVisibleItemPosition();
View firstVisiableChildView = layoutManager.getChildAt(position)但是下面這種就不是獲取第一個(gè)可見的child,而是獲得所有view list 的第一個(gè)child。但是滑動(dòng)一段距離后它總是返回null,即第一個(gè)child被recycle后,總是返回null。
//Don't use this function to get the first item, it will return null when the first item is recycled. LinearLayoutManager layoutManager = (LinearLayoutManager) this.getLayoutManager(); View child2 = layoutManager.findViewByPosition();
到此這篇關(guān)于Android獲取RecyclerView滑動(dòng)距離方法詳細(xì)講解的文章就介紹到這了,更多相關(guān)Android獲取RecyclerView滑動(dòng)距離內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
android View 繪制完成監(jiān)聽的實(shí)現(xiàn)方法
今天小編就為大家分享一篇android View 繪制完成監(jiān)聽的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09
Android連接服務(wù)器端的Socket的實(shí)例代碼
這篇文章主要介紹了Android連接服務(wù)器端的Socket的實(shí)例代碼,需要的朋友可以參考下2017-05-05
Android 監(jiān)聽?wèi)?yīng)用前/后臺(tái)切換實(shí)例代碼
本篇文章主要介紹了Android 監(jiān)聽?wèi)?yīng)用前/后臺(tái)切換實(shí)例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-06-06
詳解Android中Handler的實(shí)現(xiàn)原理
這篇文章主要為大家詳細(xì)介紹了Android中Handler的實(shí)現(xiàn)原理,本文深入分析 Android 的消息處理機(jī)制,了解 Handler 的工作原理,感興趣的小伙伴們可以參考一下2016-04-04
Android相機(jī)Camera基礎(chǔ)知識(shí)
這篇文章主要為大家詳細(xì)介紹了Android相機(jī)Camera基礎(chǔ)知識(shí),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-01-01
Android Studio下Flutter環(huán)境搭建圖文教程
這篇文章主要為大家詳細(xì)介紹了Android Studio下Flutter環(huán)境搭建圖文教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07
Android PopupWindow使用方法小結(jié)
這篇文章主要為大家詳細(xì)介紹了Android PopupWindow使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06

