使用 RecyclerView 實現 Gallery 畫廊效果,并控制 Item 停留位置
RecyclerView 作為一個列表滑動控件,我們都知道它既可以橫向滑動,也可以豎直滑動,可以實現線性布局管理,瀑布流布局管理,還有 GridView 布局管理。其實我們可以控制其 Item 的停留位置,并使其實現畫廊效果。如果大家熟悉 SnapHelper 的話,估計大家就都會了。
什么是 SnapHelper
SnapHelper 的實現原理就是是監聽 RecyclerView.OnFlingListener 中的 onFling 接口。support library 中只提供了一個繼承類 LinearSnapHelper ,LinearSnapHelper 是抽象類 SnapHelper 的具體實現。
通過 LinearSnapHelper,我們就可以使 RecyclerView 實現類似 ViewPager 的功能,無論怎么滑動最終都會停留在列表頁面正中間。
SnapHelper 和 ViewPager 的區別就是 ViewPager 一次只能滑動一頁,而 RecyclerView + SnapHelper 的方式可以實現一次滑動好幾頁。
效果如下:
居中實現方式
使用 SnapHelper 配合 RecyclerView 實現控制 Item 位置居中顯示,非常簡單,官方默認提供的 LinearSnapHelper 就是居中的,我們直接使用即可。
代碼如下:
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(linearLayoutManager);
new LinearSnapHelper().attachToRecyclerView(recyclerView);
自定義 SnapHelper
官方提供的默認是居中顯示,其實我們也可以自定義,比如:靠左顯示,讓可見的第一個 Item 居左顯示。
效果圖如下
自定義 SnapHelper ,一般需要實現兩個方法:
- int[] calculateDistanceToFinalSnap(RecyclerView.LayoutManager layoutManager, View targetView) 當拖拽或滑動結束時會回調該方法,返回一個out = int[2],out[0]x軸,out[1] y軸,這就是我們需要修改的位置偏移量
- View findSnapView(RecyclerView.LayoutManager layoutManager) 該方法返回上面方法中需要的 targetView 。
代碼如下
public classCustomSnapHelperextendsLinearSnapHelper{
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;
}
privateintdistanceToStart(View targetView, OrientationHelper helper){
return helper.getDecoratedStart(targetView) - helper.getStartAfterPadding();
}
@Override
publicViewfindSnapView(RecyclerView.LayoutManager layoutManager){
return findStartView(layoutManager, getHorizontalHelper(layoutManager));
}
privateViewfindStartView(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);
}
privateOrientationHelpergetHorizontalHelper(
RecyclerView.LayoutManager layoutManager) {
if (mHorizontalHelper == null) {
mHorizontalHelper = OrientationHelper.createHorizontalHelper(layoutManager);
}
return mHorizontalHelper;
}
}
調用自定義的 SnapHelper 代碼如下,配合 RecyclerView:
CustomSnapHelper mMySnapHelper = new CustomSnapHelper();
mMySnapHelper.attachToRecyclerView(rv);
最后,其實垂直方向也可以實現哦,大家可以嘗試一下垂直方向的使用方式是不是非常簡單。
來自:http://godcoder.me/2017/02/06/使用 RecyclerView 實現 Gallery 畫廊效果,并控制 Item 停留位置/