348

Android开发:RecyclerView平滑流畅的滑动到指定位置

 6 years ago
source link: https://juejin.im/post/59e5f3a8518825579d131417
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Android开发:RecyclerView平滑流畅的滑动到指定位置

2017年10月17日 12:14 ·  阅读 12105

在项目中,想使RecyclerView慢慢的平缓滑动指定位置,于是使用:

RecyclerView.smoothScrollToPosition(int);复制代码

发现效果并不理想,滑动过程很突兀,很快就滑动到了指定位置,并没有像函数名那样smooth(流畅的,平滑的),也就是说smoothScrollToPosition没有滑动效果,黑人问号???

本文原创作者MichaelX,掘金链接:https://juejin.cn/user/3016715634743479,转载请注明出处。复制代码

既然函数名是流畅平缓的滑动到指定位置,为什么并不理想呢?查看源码如下:

 public void smoothScrollToPosition(int position) {
        // ···省略无关代码,mLayout是该RecyclerView的LayoutManager对象
        mLayout.smoothScrollToPosition(this, mState, position);
    }复制代码

所以实际上是调用RecyclerView.LayoutManager.smoothScrollToPosition()方法,这是个抽象方法。由于笔者项目中是LinearLayoutManager于是找到其具体实现如下:

 @Override
        public void smoothScrollToPosition(RecyclerView recyclerView,
                                           RecyclerView.State state, final int position) {

            LinearSmoothScroller smoothScroller = new LinearSmoothScroller(context);

            smoothScroller.setTargetPosition(position);
            startSmoothScroll(smoothScroller);
        }复制代码

生成一个RecyclerView.SmoothScroller的子类LinearSmoothScroller对象smoothScroller,接着利用smoothScroller去完成剩下的滑动工作。

于是进去LinearSmoothScroller看看。重大发现---里面有一个跟滑动速度相关的函数:

    /**
     * Calculates the scroll speed.
     * 计算滑动速度
     * 返回:滑过1px所需的时间消耗。
     */
    protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
        // MILLISECONDS_PER_INCH是常量,等于20f
        return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
    }复制代码

既然RecyclerView.smoothScrollToPosition(int);很快,是不是延长其滑动时间就可以呢?

解决smoothScrollToPosition无效

为了验证上节延长滑动时间的想法,自定义一个LinearLayoutManager:

public class SmoothScrollLayoutManager extends LinearLayoutManager {

        public SmoothScrollLayoutManager(Context context) {
            super(context);
        }

        @Override
        public void smoothScrollToPosition(RecyclerView recyclerView,
                                           RecyclerView.State state, final int position) {

            LinearSmoothScroller smoothScroller =
                    new LinearSmoothScroller(recyclerView.getContext()) {
                        // 返回:滑过1px时经历的时间(ms)。
                        @Override
                        protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
                            return 150f / displayMetrics.densityDpi;
                        }
                    };

            smoothScroller.setTargetPosition(position);
            startSmoothScroll(smoothScroller);
        }
    }复制代码

Binggo!成功!调用RecyclerView.smoothScrollToPosition(int);发现滑动速度变慢很多,不再突兀,不再突然滑过去,没有任何过渡,而是缓慢滑过去,终于名副其实的smooth

本文原创作者MichaelX,掘金链接:https://juejin.cn/user/3016715634743479,转载请注明出处。复制代码

通过自定义LinearLayoutManager,重写smoothScrollToPosition()方法中LinearSmoothScroller对象的calculateSpeedPerPixel(DisplayMetrics)方法,可以使RecyclerView.smoothScrollToPosition(int);平滑的流畅的滑动到指定位置。其他LayoutManager暂时没用到,需要读者自己尝试。

如果读者朋友们有其他的办法,欢迎留言交流。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK