網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
先說(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è)可見(jiàn)item的位置
int position = layoutManager.findFirstVisibleItemPosition();
// 獲取第一個(gè)可見(jiàn)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è)可見(jiàn)item的高度
int itemHeight = firstVisiableChildView.getHeight();
// 獲取第一個(gè)可見(jiàn)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 的平均高度 * 可見(jiàn) item 數(shù)目,不是我們需要的精確距離。
totalDy = recyclerView.getChildAt().getTop();
依靠第一個(gè)item的滑動(dòng)距離來(lái)進(jìn)行動(dòng)畫(huà)的設(shè)置,但是根據(jù)該方法得出的 totalDy 在滑動(dòng)到一定程度后清零。
這是因?yàn)閞ecyclerViewl.getChildAt(0) 返回的永遠(yuǎn)是第一個(gè)可見(jiàn)的child,不是所有view list 的第一個(gè)child,因此這種用法是得不到滑動(dòng)距離的。
另外下面這三種用法都是等價(jià)的,都是獲取第一個(gè)可見(jiàn)的child:
LinearLayoutManager layoutManager = (LinearLayoutManager) this.getLayoutManager();
View firstVisiableChildView = this.getChildAt();
View firstVisiableChildView = layoutManager.getChildAt()
int position = layoutManager.findFirstVisibleItemPosition();
View firstVisiableChildView = layoutManager.getChildAt(position)
但是下面這種就不是獲取第一個(gè)可見(jiàn)的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();
原文鏈接:https://blog.csdn.net/m0_37707561/article/details/128641390
相關(guān)推薦
- 2022-07-07 Python數(shù)據(jù)分析之?Matplotlib?散點(diǎn)圖繪制_python
- 2022-04-16 python用socket實(shí)現(xiàn)協(xié)議TCP長(zhǎng)連接框架_python
- 2022-06-21 C++超詳細(xì)講解友元的使用_C 語(yǔ)言
- 2023-10-15 centos7 虛擬機(jī)中,網(wǎng)卡不啟動(dòng)的解決方式
- 2022-12-05 關(guān)于adfuller函數(shù)返回值的參數(shù)說(shuō)明與記錄_python
- 2022-08-22 詳解golang執(zhí)行Linux?shell命令完整場(chǎng)景下的使用方法_Golang
- 2022-05-07 react中的雙向綁定你真的了解嗎_React
- 2022-03-19 C語(yǔ)言完全平方整數(shù)的判斷_C 語(yǔ)言
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支