本章目录
- Part One:改变滑动速度
- Part Two:自动滑动
RecyclerView的自动滑动本质上和我们先前讲的Android定时任务区别不大,都是设定一个时间段,然后执行下一步命令,只不过这次把定时执行的方法换成了smoothScrollToPosition。
顾名思义,smoothScrollToPosition翻译过来就是平滑地滚动到指定位置,也就是说RecyclerView通过调用smoothScrollToPosition可以滑动到指定的item。
但是smoothScrollToPosition有一个缺点,那就是尽管号称是平滑地滚动,实际来看,默认的滑动速度还是太快了。
打开RecyclerView的smoothScrollToPosition,可以看到注释有这么一句话:
红框部分翻译过来就是LayoutManager是真正负责滚动操作的,如果想要自定义一个滚动逻辑,请重写LayoutManager的smoothScrollToPosition方法。
那么,具体该怎么做呢?我们一步一步来。
Part One:改变滑动速度
- 自定义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);
}
}
- 重写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;
}
}
}
- 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的自动滑动了,逻辑上并不复杂,我们之前都已经说过其实。
- 复制定时任务代码
把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);
}
- 手动滑动
自动滑动做好了,万一用户想手动滑动,这样我们的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();
}
}
});
}
- 最后就是滑动到末尾进行跳转了
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
网友评论