RecyclerView自动滑动

2017-11-30  本文已影响0人  黄烨1121

本章目录


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
上一篇下一篇

猜你喜欢

热点阅读