天天看點

recyclerview 滑動到目前_RecyclerView 快速滑動到頂部

建立FastScrollLinearLayoutManager,繼承LinearLayoutManager

複寫smoothScrollToPosition()方法,主要複寫LinearSmoothScroller中方法

public class FastScrollLinearLayoutManager extends LinearLayoutManager {

public FastScrollLinearLayoutManager(Context context) {

super(context);

}

@Override

public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {

LinearSmoothScroller linearSmoothScroller = new LinearSmoothScroller(recyclerView.getContext()) {

@Override

public PointF computeScrollVectorForPosition(int targetPosition) {

return FastScrollLinearLayoutManager.this.computeScrollVectorForPosition(targetPosition);

}

//該方法控制速度。

//if returned value is 2 ms, it means scrolling 1000 pixels with LinearInterpolation should take 2 seconds.

@Override

protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {

//return 10F / displayMetrics.densityDpi;//可以減少時間,預設25F

return super.calculateSpeedPerPixel(displayMetrics);

}

//該方法計算滑動所需時間。在此處間接控制速度。

//Calculates the time it should take to scroll the given distance (in pixels)

@Override

protected int calculateTimeForScrolling(int dx) {

//間接計算時提高速度,也可以直接在calculateSpeedPerPixel提高

if (dx > 3000) {

dx = 3000;

}

int time = super.calculateTimeForScrolling(dx);

LogUtil.d(time);//列印時間看下

return time;

}

};

linearSmoothScroller.setTargetPosition(position);

startSmoothScroll(linearSmoothScroller);

}

}

從複寫的兩個方法可以看出,都是為了提高滑動速度。一種是直接修改速度,另外一種是通過減少距離來減少所需時間,間接提高滑動速度。

RecyclerView 滑動過程梳理

調用RecyclerView.smoothScrollToPosition(position)時

`public void smoothScrollToPosition(int position) {

//...直接調用了LayoutManager的該方法

mLayout.smoothScrollToPosition(this, mState, position);

}`

LinearLayoutManager中

@Override

public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,int position) {

LinearSmoothScroller linearSmoothScroller = new LinearSmoothScroller(recyclerView.getContext()) {

//...

};

//設定終點位置

linearSmoothScroller.setTargetPosition(position);

//開始滾動,使用LinearSmoothScroller(一直勻速滑動,當targetPosition出現在螢幕上時再減速滑動),startSmoothScroll()是LayoutManager中的方法

startSmoothScroll(linearSmoothScroller);

}

LayoutManager中

public void startSmoothScroll(SmoothScroller smoothScroller) {

//...

mSmoothScroller = smoothScroller;

//調用SmoothScroller.start()方法開始滾動,this參數指目前LayoutManager

mSmoothScroller.start(mRecyclerView, this);

}

SmoothScroller中

void start(RecyclerView recyclerView, LayoutManager layoutManager) {

//...

//使用ViewFlinger進行動畫,ViewFlinger實作了Runnable接口,并且内部使用了Scroller,這樣就可以post自己進而對RecyclerView不斷layout就可以實作滑動

mRecyclerView.mViewFlinger.postOnAnimation();

}

ViewFlinger中,這是實作滑動的重點,省略了很多代碼邏輯

private class ViewFlinger implements Runnable {

@Override

public void run() {

if (scroller.computeScrollOffset()) {

//調用SmoothScroller的onAnimation方法

smoothScroller.onAnimation(dx - overscrollX, dy - overscrollY);

}

}

}

SmoothScroller中

private void onAnimation(int dx, int dy) {

//...

if (mTargetView != null) {

// verify target position

if (getChildPosition(mTargetView) == mTargetPosition) {

//要滑動到的位置已經顯示在螢幕上,onTargetFound()方法裡update了內插補點器,由線性內插補點器變成了減速的內插補點器。

onTargetFound(mTargetView, recyclerView.mState, mRecyclingAction);

mRecyclingAction.runIfNecessary(recyclerView);

}

//...

if (mRunning) {

//再下一次滑動

onSeekTargetStep(dx, dy, recyclerView.mState, mRecyclingAction);

//調用内部類Action的runIfNecessary方法

mRecyclingAction.runIfNecessary(recyclerView);

}

}

Action中

private void runIfNecessary(RecyclerView recyclerView) {

//調用了ViewFlinger.smoothScrollBy()方法,并傳入了mDuration,mDuration是在SmoothScroller中upDate()時傳入的,就是由前文講的兩個方法共同決定的

recyclerView.mViewFlinger.smoothScrollBy(mDx, mDy, mDuration, mInterpolator);

}

ViewFlinger中開始滾動

public void smoothScrollBy(int dx, int dy, int duration, Interpolator interpolator) {

if (mInterpolator != interpolator) {

mInterpolator = interpolator;

mScroller = ScrollerCompat.create(getContext(), interpolator);

}

setScrollState(SCROLL_STATE_SETTLING);

mLastFlingX = mLastFlingY = 0;

//調用Scroller開始滾動,此處即duration

mScroller.startScroll(0, 0, dx, dy, duration);

postOnAnimation();

}

這塊粗略的按照流程說了一下滾動過程,涉及的類比較多,最終通過Scroller來進行滾動。