RecyclerView 做爲一個列表滑動控件,咱們都知道它既能夠橫向滑動,也能夠豎直滑動,能夠實現線性佈局管理,瀑布流佈局管理,還有 GridView 佈局管理。其實咱們能夠控制其 Item 的停留位置,並使其實現畫廊效果。若是你們熟悉 SnapHelper 的話,估計你們就都會了。javascript
SnapHelper 的實現原理就是是監聽 RecyclerView.OnFlingListener 中的 onFling 接口。support library 中只提供了一個繼承類 LinearSnapHelper ,LinearSnapHelper 是抽象類 SnapHelper 的具體實現。
經過 LinearSnapHelper,咱們就能夠使 RecyclerView 實現相似 ViewPager 的功能,不管怎麼滑動最終都會停留在列表頁面正中間。 java
SnapHelper 和 ViewPager 的區別就是 ViewPager 一次只能滑動一頁,而 RecyclerView + SnapHelper 的方式能夠實現一次滑動好幾頁。android
效果以下:
git
使用 SnapHelper 配合 RecyclerView 實現控制 Item 位置居中顯示,很是簡單,官方默認提供的 LinearSnapHelper 就是居中的,咱們直接使用便可。程序員
代碼以下:github
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(linearLayoutManager);
new LinearSnapHelper().attachToRecyclerView(recyclerView);複製代碼
官方提供的默認是居中顯示,其實咱們也能夠自定義,好比:靠左顯示,讓可見的第一個 Item 居左顯示。微信
自定義 SnapHelper ,通常須要實現兩個方法:ide
public class CustomSnapHelper extends LinearSnapHelper {
private OrientationHelper mHorizontalHelper;
@Override
public int[] calculateDistanceToFinalSnap(RecyclerView.LayoutManager layoutManager, View targetView) {
int[] out = new int[2];
//判斷支持水平滾動,修改水平方向的位置,是修改的out[0]的值
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();
}
@Override
public View findSnapView(RecyclerView.LayoutManager layoutManager) {
return findStartView(layoutManager, getHorizontalHelper(layoutManager));
}
private View findStartView(RecyclerView.LayoutManager layoutManager,
OrientationHelper helper) {
if (layoutManager instanceof LinearLayoutManager) {
int firstChild = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
int lastChild = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
if (firstChild == RecyclerView.NO_POSITION) {
return null;
}
//這行的做用是若是是最後一個,翻到最後一條,解決顯示不全的問題
if (lastChild == layoutManager.getItemCount() - 1) {
return layoutManager.findViewByPosition(lastChild);
}
View child = layoutManager.findViewByPosition(firstChild);
//獲取偏左顯示的Item
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 OrientationHelper getHorizontalHelper(
RecyclerView.LayoutManager layoutManager) {
if (mHorizontalHelper == null) {
mHorizontalHelper = OrientationHelper.createHorizontalHelper(layoutManager);
}
return mHorizontalHelper;
}
}複製代碼
調用自定義的 SnapHelper 代碼以下,配合 RecyclerView:佈局
CustomSnapHelper mMySnapHelper = new CustomSnapHelper();
mMySnapHelper.attachToRecyclerView(rv);複製代碼
最後,其實垂直方向也能夠實現哦,你們能夠嘗試一下垂直方向的使用方式是否是很是簡單。this
代碼 Demo 地址:github.com/loonggg/Sna…
歡迎你們關注個人技術分享公衆號:非著名程序員(smart_android)。技術文章均先首發於個人技術分享的微信公衆號。