相关文章推荐
挂过科的镜子  ·  AWVS ...·  3 月前    · 
满身肌肉的火锅  ·  MapPropertySource ...·  9 月前    · 

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

7 人关注

我正在使用一个 LinearSnapHelper 来使我的 RecyclerView 中的项目在屏幕上 "卡 "住。我正在使用一个 LinearSnapHelper 来使我的 RecyclerView 中的项目在屏幕上 "捕捉 "到位(我的卡片占据了屏幕的大部分,所以我希望它们在每次滑动/翻转/滚动时都能捕捉到位并填满屏幕)。

我正在为如何使卡片卡住而苦恼。 更快 .我试着创建了一个自定义的 LinearLayoutManager (并编辑了 scrollToPosition smoothScrollToPosition 中的 calculateSpeedPerPixel 方法),以及一个自定义的 RecyclerView (并编辑了翻转方法)。但没有任何东西能影响卡片 "扣 "入的速度。

我想问题在于,我并不真正理解 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);
    
android
android-recyclerview
linearlayoutmanager
user1743027
user1743027
发布于 2016-10-31
5 个回答
devilbrain666
devilbrain666
发布于 2019-06-19
已采纳
0 人赞同

正如郭玉龙所说,SnapHelper调用RecyclerView.smoothScrollBy()方法。它使用默认的sQuinticInterpolator。 要改变Snap的速度,你可以做以下工作。

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);

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

郭玉龙
郭玉龙
发布于 2019-06-19
0 人赞同

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

Here's the snippet of source code.

覆盖此功能,以增加或减少抓取滚动的速度。

user1743027
发布于 2019-06-19
0 人赞同

我最终通过给我的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;
    
为什么你的线性布局是自定义的,你有没有试过用标准的水平线性布局?
你需要CustomLinearLayoutManager来加快snap/scroll的速度。下面是一个例子 stackoverflow.com/a/36784136
Rohan Arora
Rohan Arora
发布于 2019-06-19
0 人赞同

我使用一个库实现了这一点 https://github.com/rubensousa/GravitySnapHelper

你也可以覆盖findTargetSnapPosition,以获得类似于pager的滚动。

调整滚动速度以增加/减少速度

    val snapHelper : GravitySnapHelper = GravitySnapHelper(Gravity.CENTER)
    // the lower the higher the speed, default is 100f
    snapHelper.scrollMsPerInch = 40f