一、了解SnapHelper
其實(shí)SnapHelper是對(duì)RecyclerView的一種拓展江掩。
SnapHelper的實(shí)現(xiàn)原理是監(jiān)聽RecyclerView.OnFlingListener中的onFling接口再悼。LinearSnapHelper是抽象類SnapHelper的具體實(shí)現(xiàn)核畴。
通過LinearSnapHelper,可以使RecyclerView實(shí)現(xiàn)類似ViewPager的功能冲九,無論怎么滑動(dòng)最終停留在某頁(yè)正中間。
二跟束、實(shí)現(xiàn)效果
1.自帶LinearSnapHelper實(shí)現(xiàn)
可以將某頁(yè)自動(dòng)居中莺奸。
LinearSnapHelper mLinearSnapHelper=new LinearSnapHelper();
mLinearSnapHelper.attachToRecyclerView(mRecyclerView);
2.自定義SnapHelper實(shí)現(xiàn)
比如,左對(duì)齊冀宴。
SnapHelper是一個(gè)抽象類灭贷,直接繼承需要實(shí)現(xiàn)的三個(gè)方法:
- 當(dāng)拖拽或滑動(dòng)結(jié)束時(shí)會(huì)回調(diào)該方法,返回一個(gè)out = int[2]略贮,out[0]x軸甚疟,out[1] y軸 ,這個(gè)值就是需要修正的你需要的位置的偏移量
public abstract int[] calculateDistanceToFinalSnap(@NonNull LayoutManager layoutManager, @NonNull View targetView);
- 上面方法有一個(gè)targetView吧 就是這個(gè)方法返回的
public abstract View findSnapView(LayoutManager layoutManager);
- 用于Fling逃延,根據(jù)速度返回你要滑到的position
public abstract int findTargetSnapPosition(LayoutManager layoutManager, int velocityX, int velocityY);
我們不直接繼承SnapHelper览妖,而是繼承他的實(shí)現(xiàn)類LinearSnapHelper
public class MySnapHelper extends LinearSnapHelper {
privateOrientationHelper mHorizontalHelper;
@Nullable
@Override
public int[] calculateDistanceToFinalSnap (RecyclerView.LayoutManager layoutManager, View targetView) {
int[] out =newint[2];
if(layoutManager.canScrollHorizontally()) {
out[0] = distanceToStart(targetView, getHorizontalHelper(layoutManager));
}else{
out[0] =0;
}return out;
}
private int distanceToStart(View targetView, OrientationHelper helper) {
return helper.getDecoratedStart(targetView) - helper.getStartAfterPadding();
}
@Nullable
@Override public View findSnapView(RecyclerView.LayoutManager layoutManager) {
return findStartView(layoutManager, getHorizontalHelper(layoutManager));
}
private View findStartView(RecyclerView.LayoutManager layoutManager,OrientationHelper helper) {
if(layoutManagerinstanceofLinearLayoutManager) {
intfirstChild = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
intlastChild = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
if(firstChild == RecyclerView.NO_POSITION) {
return null;
} if(lastChild == layoutManager.getItemCount() -1) {
return layoutManager.findViewByPosition(lastChild);
}
View child = layoutManager.findViewByPosition(firstChild);
if(helper.getDecoratedEnd(child) >= helper.getDecoratedMeasurement(child) /2&& helper.getDecoratedEnd(child) >0) {
return child;
} else{
return layoutManager.findViewByPosition(firstChild +1);
}
}
return super.findSnapView(layoutManager);
}
private OrientationHelpergetHorizontalHelper(
@NonNull
RecyclerView.LayoutManager layoutManager) {
if(mHorizontalHelper ==null) {
mHorizontalHelper = OrientationHelper.createHorizontalHelper(layoutManager);
} return mHorizontalHelper;
}
}
這里有幾點(diǎn)需要特別注意一下,
第11~24行:我們只考慮橫向左對(duì)齊揽祥,所以只要處理out[0]的值讽膏,distanceToStart()方法返回修正的偏移量。
第41~43行:這是為了解決當(dāng)翻到最后一頁(yè)的時(shí)候拄丰,最后一個(gè)Item不能完整顯示的問題(不信府树,你可以注釋了試試就知道啦)俐末。
if(lastChild == layoutManager.getItemCount() -1) {
returnlayoutManager.findViewByPosition(lastChild);
}
第47~52行:得到此時(shí)需要左對(duì)齊顯示的條目
if(helper.getDecoratedEnd(child) >= helper.getDecoratedMeasurement(child) /2
&& helper.getDecoratedEnd(child) >0) {
return child;
} else{
return la youtManager.findViewByPosition(firstChild +1);
}
最后只要用上我們自己的SnapHelper,就可以輕松搞定了奄侠。
MySnapHelper mMySnapHelper=new MySnapHelper();
mMySnapHelper.attachToRecyclerView(mRecyclerView);
已經(jīng)實(shí)現(xiàn)的庫(kù):https://github.com/rubensousa/RecyclerViewSnap
參考文章:http://blog.csdn.net/whitley_gong/article/details/52421215