Android LinearSnapHelper - 如何增加滚动/"捕捉"速度?

7
我正在使用LinearSnapHelper来让我的RecyclerView中的项目"自动吸附"到屏幕上(我的卡片占据了大部分屏幕,所以我希望它们在每次滑动/快速滑动/滚动时都能自动吸附并填充屏幕)。
我正在思考如何让卡片更快地自动吸附。我尝试创建一个自定义的LinearLayoutManager(并编辑scrollToPositionsmoothScrollToPosition中的calculateSpeedPerPixel方法),以及一个自定义的RecyclerView(并编辑快速滑动方法)。但是这些都无法影响卡片自动吸附的速度。
我认为问题可能是我不太理解LinearSnapHelper如何将卡片滚动到位。它似乎没有使用LinearLayoutManagerscrollToPositionsmoothScrollToPosition方法。
    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(mRecyclerView);
5个回答

6

正如郭玉龙所提到的,SnapHelper 调用 RecyclerView.smoothScrollBy() 方法。而它使用默认的 sQuinticInterpolator。 要改变自动对齐的速度,您可以执行以下操作:

public class SlowdownRecyclerView extends RecyclerView {

// Change pow to control speed.
// Bigger = faster. RecyclerView default is 5.
private static final int POW = 2;

private Interpolator interpolator;

public SlowdownRecyclerView(Context context) {
    super(context);
    createInterpolator();
}

public SlowdownRecyclerView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    createInterpolator();
}

public SlowdownRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    createInterpolator();
}

private void createInterpolator(){
    interpolator = new Interpolator() {
        @Override
        public float getInterpolation(float t) {
            t = Math.abs(t - 1.0f);
            return (float) (1.0f - Math.pow(t, POW));
        }
    };
}

@Override
public void smoothScrollBy(int dx, int dy) {
    super.smoothScrollBy(dx, dy, interpolator);
}

或者你可以实现自己的插值器。


3

滚动的速度受 RecyclerView.smoothScrollBy() 影响。

这是源代码片段。

Picture

覆盖此函数以增加或减少捕捉滚动的速度。


2

我通过向RecycleView添加ScrollListener并创建自定义LinearLayoutManager和自定义smoothScrollToPosition方法来实现此操作。

    final CustomLinearLayoutManager mLayoutManager = new CustomLinearLayoutManager(getActivity());
    mRecyclerView.setLayoutManager(mLayoutManager);

    mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        private boolean scrollingUp;

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            scrollingUp = dy < 0;
        }

        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                int visiblePosition = scrollingUp ? mLayoutManager.findFirstVisibleItemPosition() : mLayoutManager.findLastVisibleItemPosition();
                int completelyVisiblePosition = scrollingUp ? mLayoutManager
                        .findFirstCompletelyVisibleItemPosition() : mLayoutManager
                        .findLastCompletelyVisibleItemPosition();
                if (visiblePosition != completelyVisiblePosition) {
                    recyclerView.smoothScrollToPosition(visiblePosition);
                    return;
                }
        }
    });

为什么你的线性布局必须是自定义的,你尝试过使用标准的水平线性布局吗? - 2cupsOfTech
您需要CustomLinearLayoutManager来加快捕捉/滚动速度。这里有一个例子https://dev59.com/0lwY5IYBdhLWcg3wwqH1#36784136/ - Jerry Sha

1
我使用了一个库 https://github.com/rubensousa/GravitySnapHelper 来实现这个功能。
你也可以重写 findTargetSnapPosition 方法,实现像翻页一样的滚动效果。
调整 scrollMsPerInch 可以增加/减少滚动速度。
    val snapHelper : GravitySnapHelper = GravitySnapHelper(Gravity.CENTER)
    
    // the lower the higher the speed, default is 100f
    snapHelper.scrollMsPerInch = 40f

    snapHelper.attachToRecyclerView(binding?.mRecyclerView)

-1
其实你可以通过简单地复制/粘贴现有代码来修改LinearSnapHelper和SnapHelperClass,唯一需要做的就是根据你的需求在SnapHelper上设置MILLISECONDS_PER_INCH,然后使用你创建的LinearSnapHelper即可。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接