Google I/O 2019 更新
ViewPager2 来了!
在“Android 有什么新东西”(又称“Android 主题演讲”)中,Google 刚刚宣布 他们正在开发一种基于 RecyclerView 的新 ViewPager!
来自幻灯片:
像 ViewPager 一样,但更好
- 易于从 ViewPager 迁移
- 基于 RecyclerView
- 支持从右到左模式
- 允许垂直分页
- 改进的数据集更改通知
你可以在
这里检查最新版本和
此处的发布说明。还有一个
官方示例。
2021年12月更新:示例已移至另一个存储库。
个人观点:我认为这是一个非常必要的补充。最近,我在使用PagerSnapHelper
时遇到了很多问题(无限左右摆动)-请参见我打开的工单。
新答案(2016年)
现在您可以使用SnapHelper。
如果您想要类似于ViewPager的居中对齐捕捉行为,则使用PagerSnapHelper:
SnapHelper snapHelper = new PagerSnapHelper()
snapHelper.attachToRecyclerView(recyclerView)
还有一个LinearSnapHelper。我试过了,如果你用力甩动,它会一次滚动2个项目。个人认为不太喜欢,但是你可以自己决定——只需要几秒钟就能试一下。
原始答案(2016年)
在 Stack Overflow 上尝试了三种不同的解决方案后,经过许多小时的努力,我终于构建出了一个非常接近 ViewPager
行为的解决方案。
该解决方案基于 @eDizzle 的 solution,我认为我已经对其进行了足够的改进,可以说它几乎像一个 ViewPager
。
重要提示:我的 RecyclerView
项的宽度与屏幕完全相同。我没有尝试其他大小。此外,我使用它与水平的 LinearLayoutManager
。如果您想要垂直滚动,我认为您需要调整代码。
这里是代码:
public class SnappyRecyclerView extends RecyclerView {
public SnappyRecyclerView(Context context) {
super(context);
}
public SnappyRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public SnappyRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean fling(int velocityX, int velocityY) {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) getLayoutManager();
int screenWidth = Resources.getSystem().getDisplayMetrics().widthPixels;
int lastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition();
View lastView = linearLayoutManager.findViewByPosition(lastVisibleItemPosition);
int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
View firstView = linearLayoutManager.findViewByPosition(firstVisibleItemPosition);
int leftMargin = (screenWidth - lastView.getWidth()) / 2;
int rightMargin = (screenWidth - firstView.getWidth()) / 2 + firstView.getWidth();
int leftEdge = lastView.getLeft();
int rightEdge = firstView.getRight();
int scrollDistanceLeft = leftEdge - leftMargin;
int scrollDistanceRight = rightMargin - rightEdge;
if (Math.abs(velocityX) < 1000) {
if (leftEdge > screenWidth / 2) {
smoothScrollBy(-scrollDistanceRight, 0);
} else if (rightEdge < screenWidth / 2) {
smoothScrollBy(scrollDistanceLeft, 0);
} else {
if (velocityX > 0) {
smoothScrollBy(-scrollDistanceRight, 0);
} else {
smoothScrollBy(scrollDistanceLeft, 0);
}
}
return true;
} else {
if (velocityX > 0) {
smoothScrollBy(scrollDistanceLeft, 0);
} else {
smoothScrollBy(-scrollDistanceRight, 0);
}
return true;
}
}
@Override
public void onScrollStateChanged(int state) {
super.onScrollStateChanged(state);
if (state == SCROLL_STATE_IDLE) {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) getLayoutManager();
int screenWidth = Resources.getSystem().getDisplayMetrics().widthPixels;
int lastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition();
View lastView = linearLayoutManager.findViewByPosition(lastVisibleItemPosition);
int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
View firstView = linearLayoutManager.findViewByPosition(firstVisibleItemPosition);
int leftMargin = (screenWidth - lastView.getWidth()) / 2;
int rightMargin = (screenWidth - firstView.getWidth()) / 2 + firstView.getWidth();
int leftEdge = lastView.getLeft();
int rightEdge = firstView.getRight();
int scrollDistanceLeft = leftEdge - leftMargin;
int scrollDistanceRight = rightMargin - rightEdge;
if (leftEdge > screenWidth / 2) {
smoothScrollBy(-scrollDistanceRight, 0);
} else if (rightEdge < screenWidth / 2) {
smoothScrollBy(scrollDistanceLeft, 0);
}
}
}
}
享受!
LinearLayoutManager
来完成的,其中所有视图的大小都是常规的。除了上面的代码片段之外,不需要其他任何东西。 - razzledazzleLinearSnapHelper
的另一种解决方案。 - razzledazzle