Android LinearSnapHelper - 如何提高滚动/"捕捉"速度?

4 android android-recyclerview linearlayoutmanager

我正在使用LinearSnapHelper将我的RecyclerView中的项目"捕捉"到屏幕上"卡住"(我的卡占据了大部分屏幕,因此我希望它们能够卡入到位并在每次滑动/滚动/滚动时填充屏幕) .

我正在努力解决如何让卡片更快地卡入到位的问题.我已经尝试创建自定义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);
Run Code Online (Sandbox Code Playgroud)

dev*_*666 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);
}
Run Code Online (Sandbox Code Playgroud)

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


小智 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;
                }
        }
    });
Run Code Online (Sandbox Code Playgroud)