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

时间:2016-10-30 23:04:13

标签: android android-recyclerview linearlayoutmanager

我使用LinearSnapHelper在我的RecyclerView" snap"屏幕上的位置(我的卡占据了屏幕的大部分,因此我希望它们能够卡入到位并在每次滑动/滚动/滚动时填充屏幕。)

我正在努力解决如何让卡片快速移动更快。我尝试过创建自定义LinearLayoutManager(并在scrollToPosition或smoothScrollToPosition中编辑calculateSpeedPerPixel方法),以及自定义RecyclerView(并编辑fling方法)。但没有什么能影响卡片的速度和快速消费。到位。

我想问题是我并不真正理解LinearSnapHelper"如何滚动"卡到位。它似乎没有使用LinearLayoutManager的scrollToPosition或smoothScrollToPosition方法。

有任何帮助吗?非常感谢!

    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 个答案:

答案 0 :(得分:5)

正如郭玉龙所说,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);
}

或者您可以实现自己的插补器。

答案 1 :(得分:3)

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

以下是源代码片段。

Picture

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

答案 2 :(得分: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;
                }
        }
    });

答案 3 :(得分:0)

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

答案 4 :(得分:0)

我使用库 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)