android recyclerview 是否能上滑动
2017-11-14 · 让每个孩子都能正常讲话,是我们最大的心愿
阳光语言矫正学校
1992年开始语音病理学研究,北京、上海 、长春设有校区,功能性构音障碍、腭裂语音障碍、听力言语障碍、语言发育迟缓、口吃等多个语音矫正和训练项目,对大舌头 口吃等各种语言障碍有数万例矫正经验
向TA提问
关注
展开全部
使用RecyclerView时,调用smoothScrollToPostion()方法滑动到指定位置,但是条目很多时滑动的很慢,本篇文章就是实现RecyclerView的快速滑动。
先介绍如何实现,然后再介绍原理。
实现代码创建FastScrollLinearLayoutManager,继承LinearLayoutManager复moothScrollToPosition()方法,主要复写LinearSmoothScroller中方法
代码如下,解释全在注释中:
public class FastScrollLinearLayoutManager extends LinearLayoutManager {
public FastScrollLinearLayoutManager(Context context) { super(context);
} @Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
LinearSmoothScroller linearSmoothScroller = new LinearSmoothScroller(recyclerView.getContext()) { @Override
public PointF computeScrollVectorForPosition(int targetPosition) { return FastScrollLinearLayoutManager.this.computeScrollVectorForPosition(targetPosition);
} //该方法控制速度。
//if returned value is 2 ms, it means scrolling 1000 pixels with LinearInterpolation should take 2 seconds.
@Override
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) { /*
mdpi上, 1英寸有160个像素点, 25/160,
xxhdpi,1英寸有480个像素点, 25/480,
*/
//return 10F / displayMetrics.densityDpi;//可以减少时间,默认25F
return super.calculateSpeedPerPixel(displayMetrics);
//Calculates the time it should take to scroll the given distance (in pixels)
protected int calculateTimeForScrolling(int dx) { /*
控制距离, 然后根据上面那个方(calculateSpeedPerPixel())提供的速度算出时间,默认一次 滚动 TARGET_SEEK_SCROLL_DISTANCE_PX = 10000个像素, 在此处可以减少该值来达到减少滚动时间的目的.
*/
//间接计算时提高速度,也可以直接在calculateSpeedPerPixel提高
if (dx > 3000) {
dx = 3000;
} int time = super.calculateTimeForScrolling(dx);
LogUtil.d(time);//打印时间看下
}
};
linearSmoothScroller.setTargetPosition(position);
startSmoothScroll(linearSmoothScroller);
}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
从复写的两个方法可以看出,都是为了提高滑动速度。一种是直接修改速度,另外一种是通过减少距离来减少所需时间,间接提高滑动速度。
这两种方法都可以,看自己所需。接下来就讲讲实现的原理。这块我只是梳理的大致的流程,不过至此你已经可以实现快速滑动了。
2. RecyclerView 滑动过程梳理
1.调用RecyclerView.smoothScrollToPosition(position)时public void moothScrollToPosition(int position) { //...直接调用了LayoutManage的该方法
}1234
2.LinearLayoutManager中@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
LinearSmoothScroller linearSmoothScroller = new LinearSmoothScroller(recyclerView.getContext()) { //...
}; //设置终点位置
linearSmoothScroller.setTargetPosition(position); //开始滚动,使用LinearSmoothScroller(一直匀速滑动,当targetPosition出现在屏幕上时再减速滑动),startSmoothScroll()是LayoutManager中的方法
startSmoothScroll(linearSmoothScroller);
}1234567891011
3.LayoutManager中public void startSmoothScroll(SmoothScroller smoothScroller) { //...
mSmoothScroller = smoothScroller; //调用SmoothScroller.start()方法开始滚动,this参数指当前LayoutManager
mSmoothScroller.start(mRecyclerView, this);
}123456
4.SmoothScroller中
void start(RecyclerView recyclerView, LayoutManager layoutManager) { //...
//使用ViewFlinger进行动画,ViewFlinger实现了Runnable接口,并且内部使用了Scroller,这样就可以post自己进而对RecyclerView不断layout就可以实现滑动
mRecyclerView.mViewFlinger.postOnAnimation();
}12345
5.ViewFlinger中,这是实现滑动的重点,省略了很多代码逻辑
private class ViewFlinger implements Runnable {
@Override
public void run() { if (scroller.computeScrollOffset()) { //调用SmoothScroller的onAnimation方法
smoothScroller.onAnimation(dx - overscrollX, dy - overscrollY);
}
}
}123456789
6.SmoothScroller中private void onAnimation(int dx, int dy) { //...
if (mTargetView != null) { // verify target position
if (getChildPosition(mTargetView) == mTargetPosition) { //要滑动到的位置已经显示在屏幕上,onTargetFound()方法里update了差值器,由线性差值器变成了减速的差值器。
onTargetFound(mTargetView, recyclerView.mState, mRecyclingAction);
mRecyclingAction.runIfNecessary(recyclerView);
} //...
if (mRunning) { //再下一次滑动
onSeekTargetStep(dx, dy, recyclerView.mState, mRecyclingAction); //调用内部类Action的runIfNecessary方法
mRecyclingAction.runIfNecessary(recyclerView);
}
}12345678910111213141516171819
7.Action中 private void runIfNecessary(RecyclerView recyclerView) { //调用了ViewFlinger.smoothScrollBy()方法,并传入了mDuration,mDuration是在SmoothScroller中upDate()时传入的,就是由前文讲的两个方法共同决定的
recyclerView.mViewFlinger.smoothScrollBy(mDx, mDy, mDuration, mInterpolator);
}1234
8.ViewFlinger中开始滚动 public void smoothScrollBy(int dx, int dy, int duration, Interpolator interpolator) { if (mInterpolator != interpolator) {
mInterpolator = interpolator;
mScroller = ScrollerCompat.create(getContext(), interpolator);
}
setScrollState(SCROLL_STATE_SETTLING);
mLastFlingX = mLastFlingY = 0; //调用Scroller开始滚动,此处即duration
mScroller.startScroll(0, 0, dx, dy, duration);
postOnAnimation();
}1234567891011
这块粗略的按照流程说了一下滚动过程,涉及的类比较多,最终通过Scroller来进行滚动。
结语:本篇文章实现了RecyclerView的快速滚动,但需要注意一个问题:如果你的Item比较复杂,滚动起来会卡顿。 这个在看源码时的一个注释里面有提到,后来实践时确实也发现。不得不说微信朋友圈滑动起来的真的快,它用的是ListView,貌似开启了FastEnable属性。 同时也可以仿照知乎,先使用RecyclerView.scrollToPosition(position)直接滑动到某一个位置后再使用smoothScrollToPosition(0)滑动到顶部。这块在RecyclerView里的Action类中jumpTo()的注释里有提到,如果很远的话可以先到一个位置后再滑动。
先介绍如何实现,然后再介绍原理。
实现代码创建FastScrollLinearLayoutManager,继承LinearLayoutManager复moothScrollToPosition()方法,主要复写LinearSmoothScroller中方法
代码如下,解释全在注释中:
public class FastScrollLinearLayoutManager extends LinearLayoutManager {
public FastScrollLinearLayoutManager(Context context) { super(context);
} @Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
LinearSmoothScroller linearSmoothScroller = new LinearSmoothScroller(recyclerView.getContext()) { @Override
public PointF computeScrollVectorForPosition(int targetPosition) { return FastScrollLinearLayoutManager.this.computeScrollVectorForPosition(targetPosition);
} //该方法控制速度。
//if returned value is 2 ms, it means scrolling 1000 pixels with LinearInterpolation should take 2 seconds.
@Override
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) { /*
mdpi上, 1英寸有160个像素点, 25/160,
xxhdpi,1英寸有480个像素点, 25/480,
*/
//return 10F / displayMetrics.densityDpi;//可以减少时间,默认25F
return super.calculateSpeedPerPixel(displayMetrics);
//Calculates the time it should take to scroll the given distance (in pixels)
protected int calculateTimeForScrolling(int dx) { /*
控制距离, 然后根据上面那个方(calculateSpeedPerPixel())提供的速度算出时间,默认一次 滚动 TARGET_SEEK_SCROLL_DISTANCE_PX = 10000个像素, 在此处可以减少该值来达到减少滚动时间的目的.
*/
//间接计算时提高速度,也可以直接在calculateSpeedPerPixel提高
if (dx > 3000) {
dx = 3000;
} int time = super.calculateTimeForScrolling(dx);
LogUtil.d(time);//打印时间看下
}
};
linearSmoothScroller.setTargetPosition(position);
startSmoothScroll(linearSmoothScroller);
}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
从复写的两个方法可以看出,都是为了提高滑动速度。一种是直接修改速度,另外一种是通过减少距离来减少所需时间,间接提高滑动速度。
这两种方法都可以,看自己所需。接下来就讲讲实现的原理。这块我只是梳理的大致的流程,不过至此你已经可以实现快速滑动了。
2. RecyclerView 滑动过程梳理
1.调用RecyclerView.smoothScrollToPosition(position)时public void moothScrollToPosition(int position) { //...直接调用了LayoutManage的该方法
}1234
2.LinearLayoutManager中@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
LinearSmoothScroller linearSmoothScroller = new LinearSmoothScroller(recyclerView.getContext()) { //...
}; //设置终点位置
linearSmoothScroller.setTargetPosition(position); //开始滚动,使用LinearSmoothScroller(一直匀速滑动,当targetPosition出现在屏幕上时再减速滑动),startSmoothScroll()是LayoutManager中的方法
startSmoothScroll(linearSmoothScroller);
}1234567891011
3.LayoutManager中public void startSmoothScroll(SmoothScroller smoothScroller) { //...
mSmoothScroller = smoothScroller; //调用SmoothScroller.start()方法开始滚动,this参数指当前LayoutManager
mSmoothScroller.start(mRecyclerView, this);
}123456
4.SmoothScroller中
void start(RecyclerView recyclerView, LayoutManager layoutManager) { //...
//使用ViewFlinger进行动画,ViewFlinger实现了Runnable接口,并且内部使用了Scroller,这样就可以post自己进而对RecyclerView不断layout就可以实现滑动
mRecyclerView.mViewFlinger.postOnAnimation();
}12345
5.ViewFlinger中,这是实现滑动的重点,省略了很多代码逻辑
private class ViewFlinger implements Runnable {
@Override
public void run() { if (scroller.computeScrollOffset()) { //调用SmoothScroller的onAnimation方法
smoothScroller.onAnimation(dx - overscrollX, dy - overscrollY);
}
}
}123456789
6.SmoothScroller中private void onAnimation(int dx, int dy) { //...
if (mTargetView != null) { // verify target position
if (getChildPosition(mTargetView) == mTargetPosition) { //要滑动到的位置已经显示在屏幕上,onTargetFound()方法里update了差值器,由线性差值器变成了减速的差值器。
onTargetFound(mTargetView, recyclerView.mState, mRecyclingAction);
mRecyclingAction.runIfNecessary(recyclerView);
} //...
if (mRunning) { //再下一次滑动
onSeekTargetStep(dx, dy, recyclerView.mState, mRecyclingAction); //调用内部类Action的runIfNecessary方法
mRecyclingAction.runIfNecessary(recyclerView);
}
}12345678910111213141516171819
7.Action中 private void runIfNecessary(RecyclerView recyclerView) { //调用了ViewFlinger.smoothScrollBy()方法,并传入了mDuration,mDuration是在SmoothScroller中upDate()时传入的,就是由前文讲的两个方法共同决定的
recyclerView.mViewFlinger.smoothScrollBy(mDx, mDy, mDuration, mInterpolator);
}1234
8.ViewFlinger中开始滚动 public void smoothScrollBy(int dx, int dy, int duration, Interpolator interpolator) { if (mInterpolator != interpolator) {
mInterpolator = interpolator;
mScroller = ScrollerCompat.create(getContext(), interpolator);
}
setScrollState(SCROLL_STATE_SETTLING);
mLastFlingX = mLastFlingY = 0; //调用Scroller开始滚动,此处即duration
mScroller.startScroll(0, 0, dx, dy, duration);
postOnAnimation();
}1234567891011
这块粗略的按照流程说了一下滚动过程,涉及的类比较多,最终通过Scroller来进行滚动。
结语:本篇文章实现了RecyclerView的快速滚动,但需要注意一个问题:如果你的Item比较复杂,滚动起来会卡顿。 这个在看源码时的一个注释里面有提到,后来实践时确实也发现。不得不说微信朋友圈滑动起来的真的快,它用的是ListView,貌似开启了FastEnable属性。 同时也可以仿照知乎,先使用RecyclerView.scrollToPosition(position)直接滑动到某一个位置后再使用smoothScrollToPosition(0)滑动到顶部。这块在RecyclerView里的Action类中jumpTo()的注释里有提到,如果很远的话可以先到一个位置后再滑动。
展开全部
recyclerview可以 向上滑动
问题有点不明确,recyclerview是可以上拉下滑的 ,跟listview一样的
1、如果是要问滑动到固定位置:
RecyclerView提供的用于控制移动的方法有2个
- scrollToPosition(int)
这个方法的作用是显示指定项,就是把你想置顶的项显示出来,但是在屏幕的什么位置是不管的,只要那一项现在看得到了,那它就罢工了!
- scrollBy(int x,int y)
这个方法是自己去控制移动的距离,单位应该是像素。
2、监听滚动
有两种方式可以监听滚动事件:
1.setOnScrollListener(OnScrollListener listener)
2.addOnScrollListener(OnScrollListener listener)
其中setOnScrollListener由于可能出现空指针的风险,已经过时。建议用addOnScrollListener。
问题有点不明确,recyclerview是可以上拉下滑的 ,跟listview一样的
1、如果是要问滑动到固定位置:
RecyclerView提供的用于控制移动的方法有2个
- scrollToPosition(int)
这个方法的作用是显示指定项,就是把你想置顶的项显示出来,但是在屏幕的什么位置是不管的,只要那一项现在看得到了,那它就罢工了!
- scrollBy(int x,int y)
这个方法是自己去控制移动的距离,单位应该是像素。
2、监听滚动
有两种方式可以监听滚动事件:
1.setOnScrollListener(OnScrollListener listener)
2.addOnScrollListener(OnScrollListener listener)
其中setOnScrollListener由于可能出现空指针的风险,已经过时。建议用addOnScrollListener。
本回答被提问者采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询