Android Recyclerview Horizo​​ntal - Snappy Scroll Effect

时间:2016-12-07 11:51:36

标签: android android-recyclerview android-cardview

我在cardview中使用RecyclerView并使RecyclerView滚动水平我已使用如下布局管理器初始化视图:

LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(layoutManager);

目前视图中的项目无休止/平滑滚动。当屏幕上显示一个项目时,我希望它停止,几乎就像一个活泼的效果。这可以实现吗?

提前致谢。

2 个答案:

答案 0 :(得分:2)

我用过这个课:

<强> SnappyRecyclerView

package icn.premierandroid.misc;

import android.content.Context;
import android.content.res.Resources;
import android.support.annotation.Nullable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.View;

public class SnappyRecyclerView extends RecyclerView {

// Use it with a horizontal LinearLayoutManager
// Based on http://stackoverflow.com/a/29171652/4034572

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;

    // views on the screen
    int lastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition();
    View lastView = linearLayoutManager.findViewByPosition(lastVisibleItemPosition);
    int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
    View firstView = linearLayoutManager.findViewByPosition(firstVisibleItemPosition);

    // distance we need to scroll
    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) {
        // The fling is slow -> stay at the current page if we are less than half through,
        // or go to the next page if more than half through

        if (leftEdge > screenWidth / 2) {
            // go to next page
            smoothScrollBy(-scrollDistanceRight, 0);
        } else if (rightEdge < screenWidth / 2) {
            // go to next page
            smoothScrollBy(scrollDistanceLeft, 0);
        } else {
            // stay at current page
            if (velocityX > 0) {
                smoothScrollBy(-scrollDistanceRight, 0);
            } else {
                smoothScrollBy(scrollDistanceLeft, 0);
            }
        }
        return true;

    } else {
        // The fling is fast -> go to next page

        if (velocityX > 0) {
            smoothScrollBy(scrollDistanceLeft, 0);
        } else {
            smoothScrollBy(-scrollDistanceRight, 0);
        }
        return true;

    }

}

@Override
public void onScrollStateChanged(int state) {
    super.onScrollStateChanged(state);

    // If you tap on the phone while the RecyclerView is scrolling it will stop in the middle.
    // This code fixes this. This code is not strictly necessary but it improves the behaviour.

    if (state == SCROLL_STATE_IDLE) {
        LinearLayoutManager linearLayoutManager = (LinearLayoutManager) getLayoutManager();

        int screenWidth = Resources.getSystem().getDisplayMetrics().widthPixels;

        // views on the screen
        int lastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition();
        View lastView = linearLayoutManager.findViewByPosition(lastVisibleItemPosition);
        int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
        View firstView = linearLayoutManager.findViewByPosition(firstVisibleItemPosition);

        // distance we need to scroll
        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);
        }
    }
}

}
XML中的

(将您的包路由放到类中,例如我的icn.premierandroid.misc.SnappyRecyclerView

 <packagename.SnappyRecyclerView
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/recycler_view"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:scrollbars="none"
            android:layout_weight="0.34" />

如果您已经在班级中初始化RecyclerView,则无需更改任何内容。

像这样:

recyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
                // LinearLayoutManager is used here, this will layout the elements in a similar fashion
                // to the way ListView would layout elements. The RecyclerView.LayoutManager defines how
                // elements are laid out.
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(mLayoutManager);

这应该只满足屏幕元素的全宽,正如您所要求的那样。

答案 1 :(得分:1)

您正在寻找的是捕捉效果。

我没有亲自使用过本课程,但我相信这对你有用。

https://gist.github.com/lauw/fc84f7d04f8c54e56d56

这样做,扩展当前Android的recyclerview并为其添加捕捉功能。

将此类添加到项目中,并使用当前的recyclerview替换recyclerview。

您可以使用 setSnapEnabled() 方法将项目捕捉到屏幕上。