很早以前,上拉加载下拉刷新这种交互方式一经推出,就火炸了。若是你在两三年前就接触过android开发,你必定据说过PullToRefreshListView这个开源框架,使用起来很简单,首先感谢伟大的做者开源这么优秀的做品,可是对于新手来说,这个框架有些过于庞大了,类和方法实在太多,定制功能太复杂,而且不得不说,再使用过程当中,这个框架的局限性很大,说到底他只是个ListView,当你和其余可滑动控件一块儿套用时,就会出现各类的问题,而且这个框架的做者已经好几年没有维护过他了。
我在git上尝试查找能替代他的家伙,万幸这个家伙被我成功发现了。虽然他的岁数也已经很大了,但到如今我仍然在使用而且也一直在维护他的代码。android-Ultra-Pull-To-Refresh,一样感谢liaohuqiu贡献这么优秀的做品。我习惯叫这个框架为Ptr,至于为何到如今我还要推荐这个框架,请听我慢慢道来:javascript
那么他没有缺点吗?固然有!java
我不会对做者的源码进行解析,毕竟网上的轮子已经不少了,重复造轮子是可耻的。也不会把修改源码的过程进行讲解,为啥?由于很早以前就改好了,到如今已经忘了具体的过程。。。哈!Sorry,这篇文章我会尽力展现框架的结构和使用方式,帮助你更好理解Ptr的优点,思路是最重要的,代码并不重要!android
gif中我展现了上拉加载,下拉刷新,标准,所有功能,空View五种状况。这里只是为了展现,其实咱们在使用过程当中,基本不会用到各类状况之间的互相切换。项目中目前只定义了两种样式的头部,第一种就是相似gif中MaterialDesign的样式,第二种就是传统样式相似PullToRefreshListView中的,这里没有展现。git
<com.leinyo.superptrwithrv.widget.ptr.PullToRefreshView
android:id="@+id/pull_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:ptr_refresh_mode="none"
app:ptr_scrollable="true"
/>复制代码
此处不废话,讲解属性含义:github
<declare-styleable name="PullToRefreshView">
<attr name="ptr_refresh_mode" format="enum">
<enum name="none" value="0"/>
<enum name="pull_from_start" value="1"/>
<enum name="pull_from_end" value="2"/>
<enum name="both" value="3"/>
</attr>
<attr name="ptr_check_login" format="boolean"/>
<attr name="ptr_header_mode" format="enum">
<enum name="material" value="0"/>
<enum name="normal" value="1"/>
</attr>
<attr name="ptr_padding_left" format="integer"/>
<attr name="ptr_padding_right" format="integer"/>
<attr name="ptr_scrollable" format="boolean"/>
</declare-styleable>复制代码
下拉刷新对应回调接口:设计模式
public interface OnPullRefreshListener {
void onPullRefresh();
}复制代码
onPullRefresh()方法会在刷新动画达到临界值之后回调。
取消下拉动画方法:架构
public void onPullRefreshComplete() {
mPtrFrameLayout.refreshComplete();
}复制代码
上拉加载对应回调接口:app
public interface OnLoadMoreListener {
void onLoadMoreRefresh();
}复制代码
取消上拉动画方法:框架
public void onLoadMoreComplete(boolean hasMore) {
mLoadMoreRecyclerViewContainer.loadMoreFinish(hasMore);
}复制代码
boolean值 表明是否还能够继续上拉 false 不会再回调onLoadMoreRefresh()!!!布局
both对应回调接口:
public interface OnRefreshListener {
void onPullRefresh();
void onLoadMoreRefresh();
}复制代码
取消所有动画方法:
public void onLoadComplete(boolean hasMore) {
mLoadMoreRecyclerViewContainer.loadMoreFinish(hasMore);
if (mCurrentRefreshMode == REFRESH_FROM_START) {
if (isRefreshing()) {
mPtrFrameLayout.refreshComplete();
}
}
}复制代码
若是咱们的返回的数据是空的,须要显示一个空页面。咱们不须要控制两个View的show与gone,ListView能作的咱们一样能到。mPullView.addEmptyView(mEmpty);
注意:addEmptyView方法不能在显示以前设置,不然会先显示空View。为啥,后面再说。
一样ListView能作的咱们也能够。mPullView.addHeaderView(mHeadView);
这一部分必定是要上图的,说多少都是无心的。
这部分你最好对Ptr有了解
怎么样?一张图是否是已经足够清楚了?看到如今你是否已经感叹做者的设计能力了?再看看上面说到做者在issues里已经回复的:下拉刷新和加载更多,不是同一个层级的功能。加载更多不该该由 UltraPTR 去实现,而应该由 Content本身去实现。
每一层级,只对应本身的业务逻辑,并不关心其余人在干什么,这就叫单一职责,解耦合。
原本以为这里应该是讲得最多的,可是写到这里,发现实在没啥可说的了,若是你真的看过Ptr的源码,相信到这里你也已经没有疑惑了,并且有种神清气爽的感受,其实就是这么简单,代码设计很重要,这也是为啥有的代码让人看得很爽,有的代码让人看了想吐
咱们上面说过真正负责显示布局的是RecyclerView了,怎么显示?固然是交给Adapter就能够了,多布局显示使用RecyclerView.Adapter的getItemViewType(int position)。须要记住的是:
咱们抽出基类BaseRefreshAdapter,里面对多布局显示有一些基础的操做,须要子类继承咱们抽出基类BaseRefreshAdapter,并实现onCreateHolder(ViewGroup parent, int viewType)(他等同于onCreateViewHolder(ViewGroup parent, int viewType))和onBindHolder(VH holder, int position)(等同于onBindViewHolder(RecyclerView.ViewHolder holder, int position)),在子类中你只须要关心你本身的Item布局就能够了,其余交给BaseRefreshAdapter中的逻辑就能够了。
这里面有泛型定义,看看源码很好理解。
这就不难理解为啥上面说过addEmptyView方法不能在显示布局以前设置了,由于若是你初始化就执行addEmptyView方法,那么当adapter初始化时,就会执行onCreateViewHolder()一系列方法,这样立刻就会显示EmptyView了,等你的真正须要的数据返回才会刷新数据布局。
本人并未侧重讲解怎么封装,怎么修改源码适配RecyclerView,也并未拆源码讲解Ptr原理,也但愿你们能理解,时间有点紧,并且轮子不少,不想再造了。
我但愿若是你看到最后,这篇文章会对你有所帮助,学习人家的设计模式的同时,你也获得了一个支持多种功能,基于RecyclerView的再封装Ptr框架(感受好绕口啊),至于为什么叫SuperPtr,纯碎是为了好玩。。。
若是您在使用过程当中,有疑问和改进意见欢迎联系我。
SupterPtr 对您的支持我深表感谢,喜欢请您star哦~~