自从使用了RecyclerView
再也回不去了,什么ListView、GridView统统让他们退休了。必须安利起来,用了才能体会它的神奇!
根据使用RecyclerView
以来,拓展的一些功能及对RecyclerView.Adapter
的封装,想在这里跟大家分享一些经验,还望指正。
功能介绍
基于对RecyclerView
在使用过程中的一些痛点写了这个开源项目 TurboRecyclerViewHelper 。功能点详见README。
本次主要介绍针对TurboRecyclerView
上拉/左滑的功能的实现及思路。
下面直接进入正题…
状态分析
以上拉加载的过程作为本次分享的一个栗子(左滑同理)。状态如下图:
我们所关心的是RecyclerView滑动到底部的状态,这个状态下是我们需要处理的临界状态
。
下文中出现的代码均为精简后的代码片段,本文重在介绍思路,所涉及的知识点假设您已经掌握,故不再展开赘述。
临界状态的限制条件
废话不多说直接看代码:
1 | if (!mLoadEnabled || canScrollEnd() || mIsLoading || isEmpty()) { |
我们从两个方面来分析可以开始处理Touch事件的条件:
客观条件
所谓客观条件即是RecyclerView滑动到底部的这个状态的物理状态,体现在代码上就是
1 | private boolean canScrollEnd() { |
这里为了简化只判断了纵向是否可以向下滑动,实际代码中这里是判断条件为ViewCompat.canScrollVertically(this, 1) || ViewCompat.canScrollHorizontally(this, 1)
这个条件返回值如果是false,则代表我们可以从这个临界状态开始处理Touch事件,否则不处理。
逻辑条件(主观条件)
逻辑条件(或者称为主观条件)是设计控件本身所考虑的限制条件。
判断条件如下:
1 | //是否允许上拉 || 是否正处于刷新状态 || 是否处理空状态 |
在以上条件下我们认为是控件本身应处于不可上拉的状态,我们不做处理。
Touch 事件的处理
在同时满足客观条件和逻辑条件下,我们就可以开始处理上拉的效果。
记录初始值
我们需要在MotionEvent.ACTION_DOWN
MotionEvent.ACTION_POINTER_DOWN
时记录初始值:
1 | mInitialMotionX = getMotionEventX(e, actionIndex); |
判断滑动是否符合预期值
在MotionEvent.ACTION_MOVE
时判断是否是上拉的状态:
1 | //LayoutManager中提供的判断是否纵向可以滑动的方法 |
记录当前Y值,且判断是否手指在上滑状态。
实现上拉效果
在自定义控件中,实现上拉效果有多种途径,例如大家常用的利用Scroller
配合scrollTo
来实现滑动,但是在RecyclerView的实现中并不支持这种方式。这个方案Close!
1 |
|
这里采用setTranslationY
来实现上拉效果,根据手指移动的距离计算出移动距离来改变RecyclerView的位置。
1 | ... |
到这里上拉的效果已经实现完毕。
复位及刷新
距离成功只差一点点。
在用户手指松开以后,我们要考虑做两件事:RecyclerView的复位及是否可以处于刷新状态。
针对复位操作,我们只需要逆向setTranslationY
值即可。这里我们采用属性动画来实现
1 | private void animateOffsetToEnd(final String propertyName, final Interpolator interpolator, float... value) { |
对于刷新我们要做的事情也比较简单,判断当前移动距离达到阈值后,回调监听事件并显示LOAING_VIEW。
1 | Log.i(TAG, "refreshing..."); |
刷新完毕后,记得通知TurboRecyclerView更新状态哦!
1 | mTurboRecyclerView.addOnLoadingMoreListener(new OnLoadMoreListener() { |
至此整个上拉到复位刷新的过程完成。
完整代码详见 TurboRecyclerView.java
希望我的分享能让您能有所收获。也欢迎支持一下这个项目~ 持续维护~
下次准备介绍一下对RecyclerView.Adapter
的封装,还请关注!😊