RecyclerView提供了以下幾個(gè)api控制RecyclerView滑動(dòng)
SmoothScrollToPosition(int position) 按一定速度滾動(dòng)到指定的位置
smoothScrollBy(int dx, int dy)? ?按一定速度滾動(dòng)指定的距離
scrollToPosition(int position)? ?跳轉(zhuǎn)到指定的位置
scrollBy(int dx,int dy)? ? 跳轉(zhuǎn)指定的距離
如果想做出像微信朋友圈雙擊滾動(dòng)到頂部的那種效果,則需要使用smoothScrollToPosition(int position)這個(gè)方法
如果直接使用的時(shí)候,發(fā)現(xiàn)滾動(dòng)速度太慢了,遠(yuǎn)遠(yuǎn)沒有微信那種效果
那么我們這個(gè)時(shí)候要怎么修改才能加快滾動(dòng)的速度呢
我們不妨來看一下smoothScrollToPosition這個(gè)方法的源碼
public void smoothScrollToPosition(int position) {
? ? if (mLayoutFrozen) {
? ? ? ? return;
}
? ? if (mLayout == null) {
? ? ? ? Log.e(TAG, "Cannot smooth scroll without a LayoutManager set. " +
? ? ? ? ? ? ? ? "Call setLayoutManager with a non-null argument.");
? ? ? ? return;
}
? ? mLayout.smoothScrollToPosition(this, mState, position);
}
可以看到,里面是mLayout調(diào)用了smoothScrollToPosition這個(gè)方法,那么mLayout是什么呢


由上面兩張圖可以看出,mLayout就是RecyclerView調(diào)用setLayoutManager時(shí)傳進(jìn)來的LayoutManager;
我們再看LayoutManager里面的smoothScrollToPosition(int position)方法,此處選擇LinearLayoutManager

我們可以看到,此處創(chuàng)建了一個(gè)LinearSmoothScroller,然后調(diào)用setTargetPosition(position)傳進(jìn)要滑動(dòng)的位置,最后調(diào)用startSmoothScroll(linearSmoothScroller)開始滑動(dòng),那么滑動(dòng)速度是在哪里設(shè)置的呢,我們接著看:
首先創(chuàng)建LinearSmoothScroller



可以看到Scroller的構(gòu)造函數(shù)里面獲取了MILLISECONDS_PER_PX這個(gè)值,再看calculateSpeedPerPixel這個(gè)方法,意思就是獲取每個(gè)px滾動(dòng)的速度,默認(rèn)使用25f/displayMetrics.densityDpi計(jì)算,所以我們只要通過減少M(fèi)ILLISECONDS_PER_PX這個(gè)值就能提高滑動(dòng)速度了

再看下MILLISECONDS_PER_PX這個(gè)值,這個(gè)是代表每個(gè)px的滾動(dòng)時(shí)間,看下哪個(gè)方法用到,如圖7所示
calculateTimeForScrolling(int dx)方法有使用,這個(gè)方法主要做的工作是把上面算的時(shí)間乘以總的滑動(dòng)距離并返回,同時(shí)為了避免當(dāng)dx非常小時(shí),返回0的情況,做了浮點(diǎn)數(shù)向上取整的操作,所以我們還可以在這里通過修改dx或修改返回?cái)?shù)值達(dá)到減少滑動(dòng)時(shí)間的目的。
回到上面
linearSmoothScroller.setTargetPosition(position);
startSmoothScroll(linearSmoothScroller);
smoothScrollToPosition還剩下這兩句代碼
setTargetPosition的意思是傳進(jìn)目的位置,以后滑動(dòng)的時(shí)候使用,然后startSmoothScroll(linearSmoothScroller)意思是調(diào)用linearSmoothScroller來進(jìn)行滑動(dòng),那么具體的滑動(dòng)算法就不詳細(xì)分析了,有興趣的人可以自己查看源碼。
那么根據(jù)上面的結(jié)論,如果要修改滑動(dòng)速度,那么新建一個(gè)LayoutManager,然后重寫SmoothScrollToPosition,然后新建一個(gè)Scroller,在Scroller里面的calculateSpeedPerPixel或者calculateTimeForScrolling方法修改對應(yīng)的參數(shù)即可修改成功
直接上代碼
????public class FastScrollLinearLayoutManager extends LinearLayoutManager {
????private float MILLISECONDS_PER_INCH = 0.03f;
????private Context mContext;
????public FastScrollLinearLayoutManager(Contextcontext) {
????????super(context);
????????mContext=context;
????????setSpeedFast();
????}
????/**
? ? ???? * 慢滑
? ? ???? */
????public void setSpeedSlow() {
????????//自己在這里用density去乘,希望不同分辨率設(shè)備上滑動(dòng)速度相同
????????//0.3f是自己估摸的一個(gè)值,可以根據(jù)不同需求自己修改
????????MILLISECONDS_PER_INCH = mContext.getResources().getDisplayMetrics().density * 0.3f;
????????}
????/**
? ? ???? * 快滑,滑動(dòng)系數(shù)自己修改,這里選了一個(gè)比較順眼的數(shù)值
? ? ???? */
????public void setSpeedFast() {
????????MILLISECONDS_PER_INCH=mContext.getResources().getDisplayMetrics().density*0.02f;
????}
????@Override
????public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
????????LinearSmoothScrollerlinear SmoothScroller = new LinearSmoothScroller(recyclerView.getContext()) {
????????@Nullable
????????@Override
????????public PointF computeScrollVectorForPosition(int targetPosition) {
????????????return FastScrollLinearLayoutManager.this.computeScrollVectorForPosition(targetPosition);
????????}
????????// 控制滑動(dòng)速度
????????@Override
????????protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
????????????// 單位速度 25F/densityDpi
????????????// return 1F / displayMetrics.densityDpi;
????????????return MILLISECONDS_PER_INCH / displayMetrics.density;
????????}
????????//該方法計(jì)算滑動(dòng)所需時(shí)間。在此處間接控制速度。
????????@Override
????????protected intcalculateTimeForScrolling(intdx){
????????????/*
? ? ? ? ? ? ? ? ? 控制距離, 然后根據(jù)上面那個(gè)方(calculateSpeedPerPixel())提供的速度算出時(shí)間,
? ? ? ? ? ? ? ? ? 默認(rèn)一次 滾動(dòng) TARGET_SEEK_SCROLL_DISTANCE_PX = 10000個(gè)像素,
? ? ? ? ? ? ? ? ? 在此處可以減少該值來達(dá)到減少滾動(dòng)時(shí)間的目的.
? ? ? ? ? ? ? ????? */
????????????//間接計(jì)算時(shí)提高速度,也可以直接在calculateSpeedPerPixel提高
????????????//? ? ? ? ? ? ? ? if (dx > 3000) {
????????????//? ? ? ? ? ? ? ? ? ? dx = 3000;
????????????//? ? ? ? ? ? ? ? }
????????????????return super.calculateTimeForScrolling(dx);
????????}
????};
????linearSmoothScroller.setTargetPosition(position);
????startSmoothScroll(linearSmoothScroller);
????}
}