Ahm*_*wad 76 android horizontal-scrolling android-recyclerview
我正在尝试使用RecyclerView在这里制作类似旋转木马的视图,我希望项目在滚动时在屏幕中间捕捉,一次一个项目.我试过用了recyclerView.setScrollingTouchSlop(RecyclerView.TOUCH_SLOP_PAGING);
但是视图仍然滚动顺畅,我也尝试使用滚动侦听器来实现我自己的逻辑,如下所示:
recyclerView.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
Log.v("Offset ", recyclerView.getWidth() + "");
if (newState == 0) {
try {
recyclerView.smoothScrollToPosition(layoutManager.findLastVisibleItemPosition());
recyclerView.scrollBy(20,0);
if (layoutManager.findLastVisibleItemPosition() >= recyclerView.getAdapter().getItemCount() - 1) {
Beam refresh = new Beam();
refresh.execute(createUrl());
}
} catch (Exception e) {
e.printStackTrace();
}
}
Run Code Online (Sandbox Code Playgroud)
从右到左的滑动现在工作正常,但不是相反,我在这里缺少什么?
raz*_*zle 132
有了LinearSnapHelper,现在很容易.
你需要做的就是:
SnapHelper helper = new LinearSnapHelper();
helper.attachToRecyclerView(recyclerView);
Run Code Online (Sandbox Code Playgroud)
更新
自25.1.0起可用,PagerSnapHelper可以帮助达到ViewPager类似的效果.像使用它一样使用它LinearSnapHelper.
旧的解决方法:
如果你希望它的行为类似于ViewPager,请尝试这样做:
LinearSnapHelper snapHelper = new LinearSnapHelper() {
@Override
public int findTargetSnapPosition(RecyclerView.LayoutManager layoutManager, int velocityX, int velocityY) {
View centerView = findSnapView(layoutManager);
if (centerView == null)
return RecyclerView.NO_POSITION;
int position = layoutManager.getPosition(centerView);
int targetPosition = -1;
if (layoutManager.canScrollHorizontally()) {
if (velocityX < 0) {
targetPosition = position - 1;
} else {
targetPosition = position + 1;
}
}
if (layoutManager.canScrollVertically()) {
if (velocityY < 0) {
targetPosition = position - 1;
} else {
targetPosition = position + 1;
}
}
final int firstItem = 0;
final int lastItem = layoutManager.getItemCount() - 1;
targetPosition = Math.min(lastItem, Math.max(targetPosition, firstItem));
return targetPosition;
}
};
snapHelper.attachToRecyclerView(recyclerView);
Run Code Online (Sandbox Code Playgroud)
上面的实现仅基于速度的方向返回当前项目旁边的位置(居中),而不管幅度如何.
前者是支持库版本24.2.0中包含的第一方解决方案.这意味着您必须将其添加到您的应用模块build.gradle或更新它.
compile "com.android.support:recyclerview-v7:24.2.0"
Run Code Online (Sandbox Code Playgroud)
Alb*_*lvo 61
重要更新:
Google已在Android支持库24.2.0(2016年8月发布)中实现了此功能.该发行说明这样说:
添加了RecyclerView.OnFlingListener以支持自定义行为以响应flings.该SnapHelper类提供一个实现专门用于捕捉孩子的意见,并 LinearSnapHelper类扩展此实现以提供类似于居中对齐捕捉行为ViewPager.
请注意,我还没有尝试使用PagerSnapHelper.我仍然使用我的解决方案,工作正常.
原始答案:
经过几个小时的尝试,我在这里找到了3个不同的解决方案,我终于建立了一个解决方案,它模仿了a中的行为ViewPager.
该解决方案基于@eDizzle 解决方案,我相信我的改进足以说它的工作方式几乎就像一个ViewPager.
重要提示:我的RecyclerView项目宽度与屏幕完全相同.我没有尝试过其他尺寸.我也用水平方式LinearLayoutManager.我想如果你想垂直滚动,你需要调整代码.
在这里你有代码:
SnapHelper snapHelper = new PagerSnapHelper();
snapHelper.attachToRecyclerView(recyclerView);
Run Code Online (Sandbox Code Playgroud)
请享用!
Boo*_*tak 38
如果目标是使RecyclerView模仿行为ViewPager有相当简单的方法
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
LinearLayoutManager layoutManager = new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false);
SnapHelper snapHelper = new PagerSnapHelper();
recyclerView.setLayoutManager(layoutManager);
snapHelper.attachToRecyclerView(mRecyclerView);
Run Code Online (Sandbox Code Playgroud)
通过使用PagerSnapHelper你可以得到像这样的行为ViewPager
eDi*_*zle 30
你需要使用findFirstVisibleItemPosition来向相反的方向前进.并且为了检测滑动的方向,您需要获得投掷速度或x的变化.我从一个略微不同的角度来解决这个问题.
创建一个扩展RecyclerView类的新类,然后覆盖RecyclerView的fling方法,如下所示:
@Override
public boolean fling(int velocityX, int velocityY) {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) getLayoutManager();
//these four variables identify the views you see on screen.
int lastVisibleView = linearLayoutManager.findLastVisibleItemPosition();
int firstVisibleView = linearLayoutManager.findFirstVisibleItemPosition();
View firstView = linearLayoutManager.findViewByPosition(firstVisibleView);
View lastView = linearLayoutManager.findViewByPosition(lastVisibleView);
//these variables get the distance you need to scroll in order to center your views.
//my views have variable sizes, so I need to calculate side margins separately.
//note the subtle difference in how right and left margins are calculated, as well as
//the resulting scroll distances.
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(user swipes to the left)
if(velocityX > 0) smoothScrollBy(scrollDistanceLeft, 0);
else smoothScrollBy(-scrollDistanceRight, 0);
return true;
}
Run Code Online (Sandbox Code Playgroud)
只需将padding和添加margin到recyclerView和recyclerView item:
回收者查看项目:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/parentLayout"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_marginLeft="8dp" <!-- here -->
android:layout_marginRight="8dp" <!-- here -->
android:layout_width="match_parent"
android:layout_height="200dp">
<!-- child views -->
</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)
回收者视图:
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="8dp" <!-- here -->
android:paddingRight="8dp" <!-- here -->
android:clipToPadding="false" <!-- important!-->
android:scrollbars="none" />
Run Code Online (Sandbox Code Playgroud)
并设置PagerSnapHelper:
int displayWidth = Resources.getSystem().getDisplayMetrics().widthPixels;
parentLayout.getLayoutParams().width = displayWidth - Utils.dpToPx(16) * 4;
SnapHelper snapHelper = new PagerSnapHelper();
snapHelper.attachToRecyclerView(recyclerView);
Run Code Online (Sandbox Code Playgroud)
dp 到 px:
public static int dpToPx(int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, Resources.getSystem().getDisplayMetrics());
}
Run Code Online (Sandbox Code Playgroud)
结果: