android recyclerview 是不是能上滑动

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android recyclerview 是不是能上滑动相关的知识,希望对你有一定的参考价值。

使用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()的注释里有提到,如果很远的话可以先到一个位置后再滑动。
参考技术A recyclerview可以 向上滑动
问题有点不明确,recyclerview是可以上拉下滑的 ,跟listview一样的
1、如果是要问滑动到固定位置:
RecyclerView提供的用于控制移动的方法有2个
- scrollToPosition(int)
这个方法的作用是显示指定项,就是把你想置顶的项显示出来,但是在屏幕的什么位置是不管的,只要那一项现在看得到了,那它就罢工了!
- scrollBy(int x,int y)
这个方法是自己去控制移动的距离,单位应该是像素。
2、监听滚动
有两种方式可以监听滚动事件:
1.setOnScrollListener(OnScrollListener listener)
2.addOnScrollListener(OnScrollListener listener)

其中setOnScrollListener由于可能出现空指针的风险,已经过时。建议用addOnScrollListener。本回答被提问者采纳

Android之解决NestedScrollView嵌套RecyclerView部分手机返回到这个页面Recyclerview顶部,而不是页面NestedScrollView顶部

1、问题

NestedScrollView嵌套Recyclerview部分手机返回到这个页面Recyclerview顶部,而不是页面NestedScrollView顶部

部分布局大致如下

		<androidx.core.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:focusableInTouchMode="true"
            android:descendantFocusability="blocksDescendants"
            android:fillViewport="true"
            app:layout_constraintBottom_toBottomOf="parent">
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">
                
                <androidx.recyclerview.widget.RecyclerView
                    android:id="@+id/recentGameRv"
                    android:layout_width="match_parent&

以上是关于android recyclerview 是不是能上滑动的主要内容,如果未能解决你的问题,请参考以下文章

android 怎么监听recyclerview是不是获取焦点

如图,Android 编程,右侧三个recyclerview布局,为啥是靠顶部,不是居中的?布局

Android6.0以上关于RecyclerView显是不全的问题

Android之解决NestedScrollView嵌套RecyclerView部分手机返回到这个页面Recyclerview顶部,而不是页面NestedScrollView顶部

Android之解决NestedScrollView嵌套RecyclerView部分手机返回到这个页面Recyclerview顶部,而不是页面NestedScrollView顶部

Android - 强大的RecyclerView