RecyclerView 平滑滚动可控制滚动速度 及 滚动的距离-终极解决方案
2018-02-03 09:25
344 查看
原创 2017-08-09 认真的 小苏
recyclerview 滑动到指定位置有好多坑,相信用过的人都遇到坑了,没办法遇到坑了,也要把它填上,今天遇到一个问题,要求 : recyclerview 平滑的滚动到指定位置并且位于屏幕中间,而且速度不能太快了。。。
看下实现效果图吧,仿腾讯新闻视频列表的滑动效果。
代码
rl_video.scrollToPosition(itemPosition);
rl_video.smoothScrollBy(0, top);
rl_video.smoothScrollToPosition(position);
这些跳转有好多蛋疼的问题,不是跳到指定位置,要不就是滑动到指定位置不准确,要不就是滑动太快,反正就是达不到要求。
于是Google了半天,终于在stackoverflow 找到了解决思路。
重写 LinearLayoutManager,为什么要重写呢,因为我是调用这个方法进行滑动的 rl_video.smoothScrollToPosition(position); 看下这个方法的源码是如何写的
如上代码所示,知其然不知其所以然,正是调用了LinearLayoutManager 中的 smoothScrollToPosition。
实现的核心代码
calculateDtToFit 方法是控制滑动的位置,可以在这个方法中所以的控制滑动的位置
calculateSpeedPerPixel 方法是控制滑动速度的
核心的主要是这两个方法。
调用方式:这样就很简单的实现了
另一种更简单的方案
LinearSmoothScroller extends RecyclerView.SmoothScroller 解决思路其实是一样的。
离,因此改变这个值就可以改变滑动的速度。为了方便设置其滑动的速度,可以自定义一个速度因子speedRatio,通过利用> > > dx*speedRatio来达到控制速度的目的。示例代码如下:
而后,实例化这个类,并设置为RecyclerView的布局,代码如下所示
RecyclerView抛掷速度的设置(此处以横向的滑动为例)
自定义一个类继承自RecyclerView,然后重载其fling()方法,在该方法中velocityX为其横向的移动距离,velocityY为其纵向的移动距离(此处以横向的滑动为例),改变这两个参数,即可以改变其相应方向滑动的距离。为了方便设置,这里同样引入一个缩放因子scale,代码示例如下:
而后,在RecyclerView中设置其缩放因子即可,代码如下:
skyLayoutManager.setSpeedRatio(0.5);
2、仿网易/QQ空间视频列表滚动连播炫酷效果(V2.0 填坑之路) 。
3、仿网易视频列表滚动连播炫酷效果(v3.0 稳定版-思想改变及优化) 稳定版-进行优化和思想上的改变。
4、RecyclerView 平滑滚动可控制滚动速度的终极解决方案。
5、仿网易视频列表连播炫酷效果 - v3.1 升级版-细节优化(网络状态切换、item点击事件等)。
持续更新中…..
recyclerview 滑动到指定位置有好多坑,相信用过的人都遇到坑了,没办法遇到坑了,也要把它填上,今天遇到一个问题,要求 : recyclerview 平滑的滚动到指定位置并且位于屏幕中间,而且速度不能太快了。。。
看下实现效果图吧,仿腾讯新闻视频列表的滑动效果。
代码
recyclerview 常用的位置跳转
((LinearLayoutManager) rl_video.getLayoutManager()).scrollToPositionWithOffset(itemPosition, 20);rl_video.scrollToPosition(itemPosition);
rl_video.smoothScrollBy(0, top);
rl_video.smoothScrollToPosition(position);
这些跳转有好多蛋疼的问题,不是跳到指定位置,要不就是滑动到指定位置不准确,要不就是滑动太快,反正就是达不到要求。
于是Google了半天,终于在stackoverflow 找到了解决思路。
看下面解决代码:
public class ScrollSpeedLinearLayoutManger extends LinearLayoutManager { public ScrollSpeedLinearLayoutManger(Context context) { super(context, VERTICAL, false); } public ScrollSpeedLinearLayoutManger(Context context, int orientation, boolean reverseLayout) { super(context, orientation, reverseLayout); } @Override public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) { Log.e("linksu", "smoothScrollToPosition(ScrollSpeedLinearLayoutManger.java:62)"); RecyclerView.SmoothScroller smoothScroller = new CenterSmoothScroller(recyclerView.getContext()); smoothScroller.setTargetPosition(position); startSmoothScroll(smoothScroller); } private class CenterSmoothScroller extends LinearSmoothScroller { CenterSmoothScroller(Context context) { super(context); } @Nullable @Override public PointF computeScrollVectorForPosition(int targetPosition) { return ScrollSpeedLinearLayoutManger.this.computeScrollVectorForPosition(targetPosition); } @Override public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd, int snapPreference) { return (boxStart + (boxEnd - boxStart) / 2) - (viewStart + (viewEnd - viewStart) / 2); } protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) { return 0.2f; } @Override protected int getVerticalSnapPreference() { return SNAP_TO_START; } } }
重写 LinearLayoutManager,为什么要重写呢,因为我是调用这个方法进行滑动的 rl_video.smoothScrollToPosition(position); 看下这个方法的源码是如何写的
public void smoothScrollToPosition(int position) { if (mLayoutFrozen) { return; } if (mLayout == null) { Log.e(TAG, "Cannot smooth scroll without a LayoutManager set. " + "Call setLayoutManager with a non-null argument."); return; } mLayout.smoothScrollToPosition(this, mState, position); }
如上代码所示,知其然不知其所以然,正是调用了LinearLayoutManager 中的 smoothScrollToPosition。
实现的核心代码
private class CenterSmoothScroller extends LinearSmoothScroller { CenterSmoothScroller(Context context) { super(context); } @Nullable @Override public PointF computeScrollVectorForPosition(int targetPosition) { return ScrollSpeedLinearLayoutManger.this.computeScrollVectorForPosition(targetPosition); } @Override public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd, int snapPreference) { return (boxStart + (boxEnd - boxStart) / 2) - (viewStart + (viewEnd - viewStart) / 2); } protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) { return 0.2f; } @Override protected int getVerticalSnapPreference() { return SNAP_TO_START; } }
calculateDtToFit 方法是控制滑动的位置,可以在这个方法中所以的控制滑动的位置
@Override public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd, int snapPreference) { return (boxStart + (boxEnd - boxStart) / 2) - (viewStart + (viewEnd - viewStart) / 2); }
calculateSpeedPerPixel 方法是控制滑动速度的
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) { return 0.2f; }
核心的主要是这两个方法。
调用方式:这样就很简单的实现了
layoutManager = new ScrollSpeedLinearLayoutManger(this); rl_video.setLayoutManager(layoutManager); rl_video.smoothScrollToPosition(position);
另一种更简单的方案
RecyclerView.SmoothScroller smoothScroller = new LinearSmoothScroller(context) { @Override protected int getVerticalSnapPreference() { return LinearSmoothScroller.SNAP_TO_START; }}; 现在设置要滚动到的位置: smoothScroller.setTargetPosition(position); 并将SmoothScroller传递给LayoutManager: layoutManager.startSmoothScroll(smoothScroller);
LinearSmoothScroller extends RecyclerView.SmoothScroller 解决思路其实是一样的。
RecyclerView滑动速度的设置(此处以横向的滑动为例)
自定义一个类继承自LayoutManager,然后重载其scrollHorizontallyBy()方法,其中在该方法中,第一个参数dx即为滑动的距>离,因此改变这个值就可以改变滑动的速度。为了方便设置其滑动的速度,可以自定义一个速度因子speedRatio,通过利用> > > dx*speedRatio来达到控制速度的目的。示例代码如下:
public class CustomSGLayoutManager extends StaggeredGridLayoutManager { private double speedRatio; public CustomSGLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } public CustomSGLayoutManager(int spanCount, int orientation) { super(spanCount, orientation); } @Override public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) { int a = super.scrollHorizontallyBy((int)(speedRatio*dx), recycler, state);//屏蔽之后无滑动效果,证明滑动的效果就是由这个函数实现 if(a == (int)(speedRatio*dx)){ return dx; } return a; } public void setSpeedRatio(double speedRatio){ this.speedRatio = speedRatio; } }
而后,实例化这个类,并设置为RecyclerView的布局,代码如下所示
private RecyclerView skyRecyclerView; public void doSomething(){ CustomSGLayoutManager skyLayoutManager = new CustomSGLayoutManager(1,StaggeredGridLayoutManager.HORIZONTAL);//实例化自定义类 skyLayoutManager.setSpeedRatio(0.82);//设置其速度因子 skyRecyclerView.setLayoutManager(skyLayoutManager); }
RecyclerView抛掷速度的设置(此处以横向的滑动为例)
自定义一个类继承自RecyclerView,然后重载其fling()方法,在该方法中velocityX为其横向的移动距离,velocityY为其纵向的移动距离(此处以横向的滑动为例),改变这两个参数,即可以改变其相应方向滑动的距离。为了方便设置,这里同样引入一个缩放因子scale,代码示例如下:
public class CustomRecyclerView extends RecyclerView { private double scale; //抛掷速度的缩放因子 public CustomRecyclerView(Context context) { super(context); } public CustomRecyclerView(Context context, AttributeSet attrs) { super(context, attrs); } public CustomRecyclerView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public void setflingScale(double scale){ this.scale = scale; } @Override public boolean fling(int velocityX, int velocityY) { velocityX *= scale; return super.fling(velocityX, velocityY); } }
而后,在RecyclerView中设置其缩放因子即可,代码如下:
skyLayoutManager.setSpeedRatio(0.5);
视频列表滚动连播技术探究系列。
1、仿网易/QQ空间视频列表滚动连播炫酷效果(V1.0 挖坑之路)。2、仿网易/QQ空间视频列表滚动连播炫酷效果(V2.0 填坑之路) 。
3、仿网易视频列表滚动连播炫酷效果(v3.0 稳定版-思想改变及优化) 稳定版-进行优化和思想上的改变。
4、RecyclerView 平滑滚动可控制滚动速度的终极解决方案。
5、仿网易视频列表连播炫酷效果 - v3.1 升级版-细节优化(网络状态切换、item点击事件等)。
持续更新中…..
相关文章推荐
- Android开发模板------ViewPager(三):实现无限循环、可嵌套RecyclerView、可控制滑动速度
- [置顶] RecyclerView常见问题解决方案,RecyclerView嵌套自动滚动,RecyclerView 高度设置wrap_content 无作用等问题
- Android ScrollView中嵌套RecyclerView布局显示不全或不显示终极解决方案!
- 关于RecyclerView滑动速度和抛掷速度的控制和改变
- 非常平滑的JS图片滚动特效代码,无缝循环,速度可自定义,鼠标悬停时停止。它的特点是JS和图片地址分离,这样做你就经易的从数据库动态调用每张图片的地址,方便控制,因此它非常的应用。
- ScrollView(RecyclerView等)为什么会自动滚动原理分析,还有阻止自动滑动的解决方案
- RecyclerView平滑地滚动到指定位置
- RecyclerView常见问题解决方案,RecyclerView嵌套自动滚动,RecyclerView 高度设置wrap_content 无作用等问题
- ScrollView(RecyclerView等)为什么会自动滚动原理分析,还有阻止自动滑动的解决方案
- ScrollView(RecyclerView等)自动滚动原理分析,还有阻止自动滑动的解决方案 ... http://www.apkbus.com/blog-945380-76974.html
- Android RecyclerView滑动固定距离 滚动指定长度
- RecyclerView调用smoothScrollToPosition() 控制滑动速度
- SwipeRefreshLayout和RecyclerView滑动冲突解决方案
- RecyclerView遇到notifyDataSetChanged无效时的解决方案
- 【转载/修改】ScrollLayout代码修正,追加模仿viewpager滚动速度
- ANDROID的WEBVIEW控件载入网页显示速度慢的究极解决方案
- 【Android】10.5 滚动视图(RecyclerView)
- viewPager控制滑动速度和时间
- viewpager广告位滑动速度控制
- 自定义TextView跑马灯效果可控制启动/停止/速度/焦点