背景
在專案中,想使RecyclerView慢慢的平緩滑動指定位置,於是使用:
RecyclerView.smoothScrollToPosition(int);複製程式碼
發現效果並不理想,滑動過程很突兀,很快就滑動到了指定位置,並沒有像函式名那樣smooth(流暢的,平滑的),也就是說smoothScrollToPosition沒有滑動效果,黑人問號???
本文原創作者MichaelX,掘金鍊接:https://juejin.im/user/56efe6461ea493005565dafd,轉載請註明出處。複製程式碼
探索歷程
既然函式名是流暢平緩的滑動到指定位置,為什麼並不理想呢?檢視原始碼如下:
public void smoothScrollToPosition(int position) {
// ···省略無關程式碼,mLayout是該RecyclerView的LayoutManager物件
mLayout.smoothScrollToPosition(this, mState, position);
}複製程式碼
所以實際上是呼叫RecyclerView.LayoutManager.smoothScrollToPosition()
方法,這是個抽象方法。由於筆者專案中是LinearLayoutManager
於是找到其具體實現如下:
@Override
public void smoothScrollToPosition(RecyclerView recyclerView,
RecyclerView.State state, final int position) {
LinearSmoothScroller smoothScroller = new LinearSmoothScroller(context);
smoothScroller.setTargetPosition(position);
startSmoothScroll(smoothScroller);
}複製程式碼
生成一個RecyclerView.SmoothScroller
的子類LinearSmoothScroller
物件smoothScroller,接著利用smoothScroller去完成剩下的滑動工作。
於是進去LinearSmoothScroller看看。重大發現—裡面有一個跟滑動速度相關的函式:
/**
* Calculates the scroll speed.
* 計算滑動速度
* 返回:滑過1px所需的時間消耗。
*/
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
// MILLISECONDS_PER_INCH是常量,等於20f
return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
}複製程式碼
既然RecyclerView.smoothScrollToPosition(int);
很快,是不是延長其滑動時間就可以呢?
解決smoothScrollToPosition無效
為了驗證上節延長滑動時間的想法,自定義一個LinearLayoutManager:
public class SmoothScrollLayoutManager extends LinearLayoutManager {
public SmoothScrollLayoutManager(Context context) {
super(context);
}
@Override
public void smoothScrollToPosition(RecyclerView recyclerView,
RecyclerView.State state, final int position) {
LinearSmoothScroller smoothScroller =
new LinearSmoothScroller(recyclerView.getContext()) {
// 返回:滑過1px時經歷的時間(ms)。
@Override
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
return 150f / displayMetrics.densityDpi;
}
};
smoothScroller.setTargetPosition(position);
startSmoothScroll(smoothScroller);
}
}複製程式碼
Binggo!成功!呼叫RecyclerView.smoothScrollToPosition(int);
發現滑動速度變慢很多,不再突兀,不再突然滑過去,沒有任何過渡,而是緩慢滑過去,終於名副其實的smooth。
本文原創作者MichaelX,掘金鍊接:https://juejin.im/user/56efe6461ea493005565dafd,轉載請註明出處。複製程式碼
結語
通過自定義LinearLayoutManager,重寫smoothScrollToPosition()方法中LinearSmoothScroller
物件的calculateSpeedPerPixel(DisplayMetrics)
方法,可以使RecyclerView.smoothScrollToPosition(int);
平滑的流暢的滑動到指定位置。其他LayoutManager暫時沒用到,需要讀者自己嘗試。
如果讀者朋友們有其他的辦法,歡迎留言交流。