简体   繁体   English

Android:控制在回收站视图上平滑滚动

[英]Android : Control Smooth scroll over recycler view

I am using Recyclerview with CardView.我正在将 Recyclerview 与 CardView 一起使用。 I am aware how to control speed on list view.我知道如何控制列表视图上的速度。 But not for Recyclerview.但不适用于 Recyclerview。

I searched a lot in found class name SmoothScroll .我在找到的类名SmoothScroll 中搜索了很多。 How to use that?怎么用那个? I have no Idea!我不知道! Right now Recyclerview by default scroll is fast.现在 Recyclerview 默认滚动速度很快。

UPDATE:更新:

I Summarized Gil Answer with this我用这个总结了吉尔的答案

It's unclear what you mean when you say " smoothScroll ".当你说“ smoothScroll ”时,你的意思不清楚。 You could be referring to the automatic " smoothScrollToPosition " which will automatically scroll to a specified position, you could be talking about manual scrolling and you could be talking about flinging.您可能指的是自动“ smoothScrollToPosition ”,它会自动滚动到指定位置,您可能指的是手动滚动,也可能指的是投掷。 For the sake of prosperity, I will attempt to answer all of these issues now.为了繁荣,我现在将尝试回答所有这些问题。

1. Automatic smooth scrolling. 1.自动平滑滚动。

Inside your layout manager, you need to implement the smoothScrollToPosition method:在你的布局管理器中,你需要实现smoothScrollToPosition方法:

    @Override
    public void smoothScrollToPosition(RecyclerView recyclerView, State state, int position)
    {
        // A good idea would be to create this instance in some initialization method, and just set the target position in this method.
        LinearSmoothScroller smoothScroller = new LinearSmoothScroller(getContext())
        {
            @Override
            public PointF computeScrollVectorForPosition(int targetPosition)
            {
                int yDelta = calculateCurrentDistanceToPosition(targetPosition);
                return new PointF(0, yDelta);
            }

            // This is the important method. This code will return the amount of time it takes to scroll 1 pixel.
            // This code will request X milliseconds for every Y DP units.
            @Override
            protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics)
            {
                return X / TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, Y, displayMetrics);
            }

        };
        smoothScroller.setTargetPosition(position);

        startSmoothScroll(smoothScroller);
    }

In this example, I use a helper method named "calculateCurrentDistanceToPosition".在这个例子中,我使用了一个名为“calculateCurrentDistanceToPosition”的辅助方法。 This can be a bit tricky, since it involves keeping track of your current scroll position, and calculating the scroll position of a given y position.这可能有点棘手,因为它涉及跟踪您当前的滚动位置,并计算给定 y 位置的滚动位置。 You can find an example of how to keep track of the recycler's scroll y here .您可以在此处找到如何跟踪回收器滚动 y 的示例。

Calculating the scroll y of a given position is really dependent on what your recycler is displaying.计算给定位置的滚动 y 实际上取决于您的回收站显示的内容。 Assuming all your items are the same height, you can calculate this by performing the following calculation:假设您的所有项目都具有相同的高度,您可以通过执行以下计算来计算:

targetScrollY = targetPosition * itemHeight

Then, to calculate the distance you need to scroll, simply subtract the current scroll y with the target scroll y:然后,要计算您需要滚动的距离,只需用目标滚动 y 减去当前滚动 y:

private int calculateCurrentDistanceToPosition(int targetPosition) {
    int targetScrollY = targetPosition * itemHeight;
    return targetScrollY - currentScrollY;
}

2. Slowing down manual scrolling. 2. 减慢手动滚动。

Once again, you need to edit your layout manager, this time - the scrollVerticallyBy method:再次,您需要编辑您的布局管理器,这一次 - scrollVerticallyBy方法:

    @Override
    public int scrollVerticallyBy(int delta, Recycler recycler, State state)
    {
       // write your limiting logic here to prevent the delta from exceeding the limits of your list.

       int prevDelta = delta;
       if (getScrollState() == SCROLL_STATE_DRAGGING)
            delta = (int)(delta > 0 ? Math.max(delta * MANUAL_SCROLL_SLOW_RATIO, 1) : Math.min(delta * MANUAL_SCROLL_SLOW_RATIO, -1));  

       // MANUAL_SCROLL_SLOW_RATIO is between 0 (no manual scrolling) to 1 (normal speed) or more (faster speed).
       // write your scrolling logic code here whereby you move each view by the given delta

        if (getScrollState() == SCROLL_STATE_DRAGGING)
            delta = prevDelta;

        return delta;
    }

Edit: In the above method, I call " getScrollState() ".编辑:在上面的方法中,我调用“ getScrollState() ”。 This is a method of RecyclerView .这是RecyclerView一种方法。 In this implementation, my custom LayoutManager is a nested class of my custom RecyclerView .在这个实现中,我的自定义LayoutManager是我的自定义RecyclerView的嵌套类。 If this doesn't work for you, you can try to grab the scroll state via some interface pattern.如果这对您不起作用,您可以尝试通过某种界面模式获取滚动状态。

3. Slow down the fling speed 3.放慢投掷速度

Here you want to scale down the fling velocity.在这里,您要缩小投掷速度。 You will need to override the fling method inside your RecyclerView subclass:您将需要覆盖 RecyclerView 子类中的fling方法:

@Override
public boolean fling(int velocityX, int velocityY)
{
     velocityY *= FLING_SCALE_DOWN_FACTOR; // (between 0 for no fling, and 1 for normal fling, or more for faster fling).

     return super.fling(velocityX, velocityY);
}

It's difficult for me to provide a more tailored solution, since you didn't post any of your code, or provide much information about your setup, but I hope this covers most bases and will help you find the best solution for you.我很难提供更量身定制的解决方案,因为您没有发布任何代码,也没有提供有关您的设置的大量信息,但我希望这涵盖了大多数基础,并能帮助您找到最适合您的解决方案。

I just simplifying Answer how to use it to control smooth scroll.我只是简化了 Answer 如何使用它来控制平滑滚动。

Create Class创建班级

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;

public class CustomRecyclerView extends RecyclerView {

    Context context;

    public CustomRecyclerView(Context context) {
        super(context);
        this.context = context;
    }

    public CustomRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomRecyclerView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean fling(int velocityX, int velocityY) {

        velocityY *= 0.7;
        // velocityX *= 0.7; for Horizontal recycler view. comment velocityY line not require for Horizontal Mode.

        return super.fling(velocityX, velocityY);
    }

}

Adjust speed by Replacing 0.7 to your value.通过将0.7替换为您的值来调整速度。

Now use this class in your XML like this.现在像这样在你的 XML 中使用这个类。

<<yourpackage>.CustomRecyclerView
    android:id="@+id/my_recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="vertical" />

Read RecyclerView in Java like.像 Java 一样阅读 RecyclerView。

CustomRecyclerView mRecyclerView;
mRecyclerView = (CustomRecyclerView) findViewById(R.id.my_recycler_view);

Simply implement smoothScrollToPosition() of your LinearLayoutManager:只需实现 LinearLayoutManager 的smoothScrollToPosition()

LinearLayoutManager layoutManager = new LinearLayoutManager(this) {

    @Override
    public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
        LinearSmoothScroller smoothScroller = new LinearSmoothScroller(this) {

            private static final float SPEED = 300f;// Change this value (default=25f)

            @Override
            protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
                return SPEED / displayMetrics.densityDpi;
            }

        };
        smoothScroller.setTargetPosition(position);
        startSmoothScroll(smoothScroller);
    }

};

使用它来平滑滚动

recyclerViewCart.isNestedScrollingEnabled = false

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM