美文网首页
RecyclerView自动滑动

RecyclerView自动滑动

作者: 黄烨1121 | 来源:发表于2017-11-30 22:53 被阅读0次

    本章目录

    • Part One:改变滑动速度
    • Part Two:自动滑动

    RecyclerView的自动滑动本质上和我们先前讲的Android定时任务区别不大,都是设定一个时间段,然后执行下一步命令,只不过这次把定时执行的方法换成了smoothScrollToPosition。
    顾名思义,smoothScrollToPosition翻译过来就是平滑地滚动到指定位置,也就是说RecyclerView通过调用smoothScrollToPosition可以滑动到指定的item。
    但是smoothScrollToPosition有一个缺点,那就是尽管号称是平滑地滚动,实际来看,默认的滑动速度还是太快了。
    打开RecyclerView的smoothScrollToPosition,可以看到注释有这么一句话:

    smoothScrollToPosition注释.png
    红框部分翻译过来就是LayoutManager是真正负责滚动操作的,如果想要自定义一个滚动逻辑,请重写LayoutManager的smoothScrollToPosition方法。
    那么,具体该怎么做呢?我们一步一步来。

    Part One:改变滑动速度

    1. 自定义LayoutManager
      由于我们使用的是横向的LinearLayoutManager,所以我们要创建一个类继承它,并重写三个参数的构造方法。
    package com.terana.mycustomview.customview;
    
    import android.content.Context;
    import android.support.v7.widget.LinearLayoutManager;
    
    public class CustomLinearLayoutManager extends LinearLayoutManager{
        private float moveSpeedPerInch= 25f;//默认移动速度
    
        public CustomLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
            super(context, orientation, reverseLayout);
        }
    }
    
    1. 重写smoothScrollToPosition
      按着官方的指示,我们重写了smoothScrollToPosition方法,点到super看看父类的实现,发现除了需要自定义一个LinearSmoothScroller外,其它代码可不变。
      重写了LinearSmoothScroller后,我们需要重写一个calculateSpeedPerPixel方法,点开父类的实现看看发现,代码很简单
        /**
         * Calculates the scroll speed.
         *
         * @param displayMetrics DisplayMetrics to be used for real dimension calculations
         * @return The time (in ms) it should take for each pixel. For instance, if returned value is
         * 2 ms, it means scrolling 1000 pixels with LinearInterpolation should take 2 seconds.
         */
        protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
            return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
        }
    

    MILLISECONDS_PER_INCH 是一个固定值25f,然后除以屏幕密度,获得移动1000像素所需要的时间。
    所以,我们想让时间变慢,只需把MILLISECONDS_PER_INCH 换成我们预先定义的moveSpeedPerInch变量,然后扩大倍数即可。
    具体代码为:

    package com.terana.mycustomview.customview;
    
    import android.content.Context;
    import android.support.v7.widget.LinearLayoutManager;
    import android.support.v7.widget.LinearSmoothScroller;
    import android.support.v7.widget.RecyclerView;
    import android.util.DisplayMetrics;
    
    public class CustomLinearLayoutManager extends LinearLayoutManager{
        private float moveSpeedPerInch = 25f;//默认移动速度
    
        public CustomLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
            super(context, orientation, reverseLayout);
        }
    
        @Override
        public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
            LinearSmoothScroller linearSmoothScroller =
                    new CustomLinearSmoothScroller(recyclerView.getContext());
            linearSmoothScroller.setTargetPosition(position);
            startSmoothScroll(linearSmoothScroller);
        }
    
        /**
         * 调用此方法,让smoothScrollToPosition的速度比原来放慢n倍
         */
        public void setSpeedSlow(int n){
            moveSpeedPerInch = 25f * n;
        }
    
        private class CustomLinearSmoothScroller extends LinearSmoothScroller{
    
            private CustomLinearSmoothScroller(Context context) {
                super(context);
            }
    
            @Override
            protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
                return moveSpeedPerInch / displayMetrics.densityDpi;
            }
        }
    }
    
    1. GalleryActivity调用
      好了,方法实现了,在GalleryActivity里把先前调用的LinearLayoutManger换成我们自定义的,然后调用setSpeedSlow方法即可减慢速度了。
        private void initRecyclerView() {
            RecyclerView recyclerView = findViewById(R.id.recyclerView_gallery);
            final List<PhotoBean> datas = getFakeDatas();
            final MyRecyclerViewAdapter adapter = new MyRecyclerViewAdapter(datas, this);
            final CustomLinearLayoutManager linearLayoutManager = new CustomLinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
            linearLayoutManager.setSpeedSlow(5);
            recyclerView.setLayoutManager(linearLayoutManager);
            new LinearSnapHelper().attachToRecyclerView(recyclerView);
            recyclerView.setAdapter(adapter);
        }
    

    Part Two:自动滑动

    滑动速度搞定了,我们就可以着手来做RecyclerView的自动滑动了,逻辑上并不复杂,我们之前都已经说过其实。

    1. 复制定时任务代码
      把MainActivity的switchContent方法复制过来,然后改名为autoMoveRecyclerView
        private void initRecyclerView() {
            RecyclerView recyclerView = findViewById(R.id.recyclerView_gallery);
            final List<PhotoBean> datas = getFakeDatas();
            final MyRecyclerViewAdapter adapter = new MyRecyclerViewAdapter(datas, this);
            final CustomLinearLayoutManager linearLayoutManager = new CustomLinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
            linearLayoutManager.setSpeedSlow(5);
            recyclerView.setLayoutManager(linearLayoutManager);
            new LinearSnapHelper().attachToRecyclerView(recyclerView);
            recyclerView.setAdapter(adapter);
            autoMoveRecyclerView(recyclerView, datas);
        }
    
        private int index = 0;
        private void autoMoveRecyclerView(final RecyclerView recyclerView, final List<PhotoBean> datas) {
            final Timer timer = new Timer();
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            if (index == datas.size()){
                                index = 0;
                                timer.cancel();
                            }
                            recyclerView.smoothScrollToPosition(index);
                            index++;
                        }
                    });
                }
            }, 50, 4000);
        }
    
    1. 手动滑动
      自动滑动做好了,万一用户想手动滑动,这样我们的index就乱了,所以要做下处理,给RecyclerView添加一个滑动监听,获取静止状态,也就是不滑动时的位置,改为index索引。
        private void initRecyclerView() {
            RecyclerView recyclerView = findViewById(R.id.recyclerView_gallery);
            final List<PhotoBean> datas = getFakeDatas();
            final MyRecyclerViewAdapter adapter = new MyRecyclerViewAdapter(datas, this);
            final CustomLinearLayoutManager linearLayoutManager = new CustomLinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
            linearLayoutManager.setSpeedSlow(5);
            recyclerView.setLayoutManager(linearLayoutManager);
            new LinearSnapHelper().attachToRecyclerView(recyclerView);
            recyclerView.setAdapter(adapter);
            autoMoveRecyclerView(recyclerView, datas);
            recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                    if (newState == RecyclerView.SCROLL_STATE_IDLE){
                        CustomLinearLayoutManager manager = (CustomLinearLayoutManager) recyclerView.getLayoutManager();
                        index = manager.findLastVisibleItemPosition();
                    }
                }
            });
        }
    
    1. 最后就是滑动到末尾进行跳转了
        private void autoMoveRecyclerView(final RecyclerView recyclerView, final List<PhotoBean> datas) {
            final Timer timer = new Timer();
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            if (index == datas.size()){
                                timer.cancel();
                                Intent intent = new Intent(GalleryActivity.this, HeartActivity.class);
                                startActivity(intent);
                            }
                            recyclerView.smoothScrollToPosition(index);
                            index++;
                        }
                    });
                }
            }, 50, 4000);
        }
    

    最终效果为:


    自动滚动.gif

    相关文章

      网友评论

          本文标题:RecyclerView自动滑动

          本文链接:https://www.haomeiwen.com/subject/kvxbbxtx.html