智能下拉刷新框架-SmartRefreshLayout
框架?下拉刷新控件还能框架化?智能?啥玩意来着?二话不多少先上Demo效果图,咱们再来探个究竟。
Github 传送门(https://github.com/scwang90/SmartRefreshLayout)
Demo
下载 APK-Demo(https://github.com/scwang90/SmartRefreshLayout/raw/master/art/app-debug.apk)
如果手机上看不到图片,可以尝试
- 点击浏览器查看
- 点击Github传送门
- 使用电脑浏览
项目演示
风格演示
框架
如果你看完了效果图,或许框架的意思应该有所了解了~~SmartRefreshLayout对下拉刷新功能进行系统的拆分、组合,主要由四个部分组成:
- RefreshLayout 下拉的基本功能,包括布局测量、滑动事件处理、参数设定等等
- RefreshContent 对不同内容的统一封装,包括判断是否可滚动、回弹判断、智能识别
- RefreshHeader 下拉头部的实现和显示
- RefreshFooter 上拉底部的实现和显示
下面是UML关系类图
通过SmartRefreshLayout框架,你可以在一个稳定强大的下拉布局中实现自己项目需求的 Header ,不用去关心滑动事件处理,不用关心子控件的回弹和滚动边界,只需关注自己真正的项目需求Header的样子和动画。
特点
这时你会问:网上其他的开源下拉控件一样的可以自定义 Header 和 Footer ,SmartRefreshLayout 和它们比起来有什么优势?
变换方式
- Translate 平行移动 特点: 最常见,HeaderView高度不会改变,
- Scale 拉伸形变 特点:在下拉和上弹(HeaderView高度改变)时候,会自动触发OnDraw事件
- FixedFront 固定在前面 特点:不会上下移动,HeaderView高度不会改变
- FixedBehind 固定在后面 特点:不会上下移动,HeaderView高度不会改变(类似微信浏览器效果)
- Screen 全屏幕 特点:固定在前面,尺寸充满整个布局
SmartRefreshLayout 的Header和Footer都有多种变换方式,适应不同风格的 Header 和 Footer,下面是不同变换方式Header的Demo
FixedBehind 固定在后面 和 Scale 拉伸形变
Screen 全屏幕 和 Translate 平行移动
独立事件
Header和Footer 可以独立的处理手指滑动事件来为动画提供操作指令,也可以使用RefreshLayout的核心接口来完成一些不寻常的操作指令。 下面的打砖块 Header中 ,Header可以独立的使用滑动事件来为游戏挡板提供指令,并同时可以调用核心接口来通知RefreshLayout上下滚动列表
智能
智能是什么玩意?有什么用?智能主要体现 SmartRefreshLayout 对未知布局的自动识别上,这样可以让我们更高效的实现我们所需的功能,也可以实现一些非寻常的功能。下面通过自定义Header 和 嵌套Layout作为内容 来解释 SmartRefreshLayout 的智能之处。
自定义Header
我们来看这一下这个伪代码例子:
<SmartRefreshLayout>
<ClassicsHeader/>
<TextView/>
<ClassicsFooter/>
</SmartRefreshLayout>
在Android Studio 中的预览效果图
对比代码和我们预想的一样,那我们来对代码做一些改动,ClassicsHeader换成一个简单的TextView,看看会发生什么?
<SmartRefreshLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:gravity="center"
android:background="#444"
android:textColor="#fff"
android:text="看看我会不会变成Header"/>
<TextView/>
<ClassicsFooter/>
</SmartRefreshLayout>
在Android Studio 中的预览效果图 和 运行效果图
这时发现我们我们替换的 TextView 自动就变成了Header,只是它还不会动。要动起来?那么太简单啦,网上随便一搜索就一大堆的 gif 。如这里:拖拖拖 ~~垃机C4D,类似的我们还可以找到很多,又如:环游东京30天:GIF版旅行指南
那我们就选择 环游东京30天:GIF版旅行指南 中的这张:
接着我们来改代码:
compile 'pl.droidsonroids.gif:android-gif-drawable:1.2.3'//一个开源gif控件
<SmartRefreshLayout>
<pl.droidsonroids.gif.GifImageView
android:layout_width="match_parent"
android:layout_height="150dp"
android:scaleType="centerCrop"
android:src="@mipmap/gif_header_repast"/>
<ListView/>
<ClassicsFooter/>
</SmartRefreshLayout>
在 Android Studio 中的预览效果图 和 运行效果图
哈哈!一行Java代码都不用写,就完成了一个自定义的Header
嵌套Layout作为内容
如果boos要求在列表的前面固定一个广告条怎么办?这好办呀,一般我们会开开心心的下下这样的代码:
<LinearLayout
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:gravity="center"
android:text="我就是boos要求加上的广告条啦"/>
<SmartRefreshLayout>
<ListView/>
</SmartRefreshLayout>
</LinearLayout>
但是在运行下拉刷新的时候,我们发现 Header是在广告条之下的,看着会别扭~,其实我们可以试试另一种方式,把广告条写到 RefreshLayout内部,看看会发生什么?
<SmartRefreshLayout>
<LinearLayout
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:gravity="center"
android:text="我就是boos要求加上的广告条啦"/>
<ListView/>
</LinearLayout>
</SmartRefreshLayout>
由于伪代码过于简单,而且运行效果过于丑陋,这里还是贴出在实际项目中的实际情况吧~
我们注意看右边的图,仔细观察手指触摸的位置和下拉效果。可以看到在列表已经滚动到中部时,轻微下拉列表是不会触发刷新的,但是如果是触摸固定的布局,则可以触发下拉。从这里可以看出 SmartRefreshLayout 对滚动边界的判断是动态的,智能的!当然如果 SmartRefreshLayout 的智能还是不能满足你,可以通过 setListener 自己实现滚动边界的判断,更为准确!
功能
简单的介绍了两大特点框架和智能,接下来也说说SmartRefreshLayout还具有的其他常用功能吧~
- 支持所有的 View(AbsListView、RecyclerView、WebView….View) 和多层嵌套的 Layout
- 支持自定义并且已经集成了很多炫酷的 Header 和 Footer
- 支持和ListView的同步滚动 和 RecyclerView、AppBarLayout、CoordinatorLayout 的嵌套滚动 NestedScrolling.
- 支持在Android Studio Xml 编辑器中预览 效果
- 支持分别在 Default(默认)、Xml、JavaCode 等三个地方设置 Header 和 Footer.
- 支持自动刷新、自动上拉加载(自动检测列表滚动到底部,而不用手动上拉).
- 支持通用的刷新监听器 OnRefreshListener 和更详细的滚动监听 OnMultiPurposeListener.
- 支持自定义回弹动画的插值器,实现各种炫酷的动画效果.
- 支持设置主题来适配任何场景的App,不会出现炫酷但很尴尬的情况.
- 支持设置多种滑动方式来适配各种效果的Header和Footer:位置平移、尺寸拉伸、背后固定、顶层固定、全屏
- 支持内容尺寸自适应 Content-wrap_content
- 支持继承重写和扩展功能,内部实现没有 private 方法和字段,继承之后都可以重写覆盖
- 支持越界回弹(Listview、RecyclerView、ScrollView、WebView…View)
使用
简单用例
1.在 buld.gradle 中添加依赖
compile 'com.scwang.smartrefresh:SmartRefreshLayout:1.0.1'
compile 'com.scwang.smartrefresh:SmartRefreshHeader:1.0.1'//如果使用了特殊的Header
2.在XML布局文件中添加 SmartRefreshLayout
<?xml version="1.0" encoding="utf-8"?>
<com.scwang.smartrefresh.layout.SmartRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/refreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="never"
android:background="#fff" />
</com.scwang.smartrefresh.layout.SmartRefreshLayout>
3.在 Activity 或者 Fragment 中添加代码
RefreshLayout refreshLayout = (RefreshLayout)findViewById(R.id.refreshLayout);refreshLayout.setOnRefreshListener(new OnRefreshListener() {
@Override
public void onRefresh(RefreshLayout refreshlayout) {
refreshlayout.finishRefresh(2000);
}
});
refreshLayout.setOnLoadmoreListener(new OnLoadmoreListener() {
@Override
public void onLoadmore(SmartRefreshLayout refreshlayout) {
refreshlayout.finishLoadmore(2000);
}
});
使用指定的 Header 和 Footer
1.方法一 全局设置
//设置全局的Header构建器
SmartRefreshLayout.setDefaultRefreshHeaderCreater(new DefaultRefreshHeaderCreater() {
@Override
public RefreshHeader createRefreshHeader(Context context, RefreshLayout layout) {
return new ClassicsHeader(context);//指定为经典Header,默认是 贝塞尔雷达Header
}
});
//设置全局的Footer构建器
SmartRefreshLayout.setDefaultRefreshFooterCreater(new DefaultRefreshFooterCreater() {
@Override
public RefreshFooter createRefreshFooter(Context context, RefreshLayout layout) {
return new ClassicsFooter(context);//指定为经典Footer,默认是 BallPulseFooter
}
});
注意:方法一 设置的Header和Footer的优先级是最低的,如果同时还使用了方法二、三,将会被其他方法取代
2.方法二 XML布局文件指定
<com.scwang.smartrefresh.layout.SmartRefreshLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/smartLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#444444"
app:srlPrimaryColor="#444444"
app:srlAccentColor="@android:color/white"
app:srlEnablePreviewInEditMode="true">
<!--srlAccentColor srlPrimaryColor 将会改变 Header 和 Footer 的主题颜色-->
<!--srlEnablePreviewInEditMode 可以开启和关闭预览功能-->
<com.scwang.smartrefresh.layout.header.ClassicsHeader
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:srlClassicsSpinnerStyle="FixedBehind"/>
<!--FixedBehind可以让Header固定在内容的背后,下拉的时候效果同微信浏览器的效果-->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/padding_common"
android:background="@android:color/white"
android:text="@string/description_define_in_xml"/>
<com.scwang.smartrefresh.layout.footer.ClassicsFooter
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:srlClassicsSpinnerStyle="FixedBehind"/>
<!--FixedBehind可以让Footer固定在内容的背后,下拉的时候效果同微信浏览器的效果-->
</com.scwang.smartrefresh.layout.SmartRefreshLayout>
注意:方法二 XML设置的Header和Footer的优先级是中等的,会被方法三覆盖。而且使用本方法的时候,Android Studio 会有预览效果,如下图:
不过不用担心,只是预览效果,运行的时候只有下拉才会出现~
3.方法三 Java代码设置
final RefreshLayout refreshLayout = (RefreshLayout) findViewById(R.id.smartLayout);//设置 Header 为 Material风格refreshLayout.setRefreshHeader(new MaterialHeader(this).setShowBezierWave(true));//设置 Footer 为 球脉冲refreshLayout.setRefreshFooter(new BallPulseFooter(this).setSpinnerStyle(SpinnerStyle.Scale));
属性 Attributes
名称 |
格式 |
描述 |
---|---|---|
srlPrimaryColor |
color |
主题颜色 |
srlAccentColor |
color |
强调颜色 |
srlReboundDuration |
integer |
释放后回弹动画时长 |
srlHeaderHeight |
dimension |
Header的标准高度 |
srlFooterHeight |
dimension |
Footer的标准高度 |
srlDragRate |
float |
显示拖动高度/真实拖动高度(默认0.5,阻尼效果) |
srlHeaderMaxDragRate |
float |
Header最大拖动高度/Header标准高度(默认2,要求>=1) |
srlFooterMaxDragRate |
float |
Footer最大拖动高度/Footer标准高度(默认2,要求>=1) |
srlEnableRefresh |
boolean |
是否开启下拉刷新功能(默认true) |
srlEnableLoadmore |
boolean |
是否开启加上拉加载功能(默认true) |
srlEnableHeaderTranslationContent |
boolean |
拖动Header的时候是否同时拖动内容(默认true) |
srlEnableFooterTranslationContent |
boolean |
拖动Footer的时候是否同时拖动内容(默认true) |
srlEnablePreviewInEditMode |
boolean |
是否在编辑模式时显示预览效果(默认true) |
srlDisableContentWhenRefresh |
boolean |
是否在刷新的时候禁止内容的一切手势操作(默认false) |
srlDisableContentWhenLoading |
boolean |
是否在加载的时候禁止内容的一切手势操作(默认false) |
方法 Method
名称 |
格式 |
描述 |
---|---|---|
setPrimaryColors |
colors |
主题强调颜色 |
setPrimaryColorsId |
colors |
主题强调颜色资源Id |
setReboundDuration |
integer |
释放后回弹动画时长 |
setHeaderHeight |
dimension |
Header的标准高度(px/dp 两个版本) |
setFooterHeight |
dimension |
Footer的标准高度(px/dp 两个版本) |
setDragRate |
float |
显示拖动高度/真实拖动高度(默认0.5,阻尼效果) |
setHeaderMaxDragRate |
float |
Header最大拖动高度/Header标准高度(默认2,要求>=1) |
setFooterMaxDragRate |
float |
Footer最大拖动高度/Footer标准高度(默认2,要求>=1) |
setEnableRefresh |
boolean |
是否开启下拉刷新功能(默认true) |
setEnableLoadmore |
boolean |
是否开启加上拉加载功能(默认true) |
setEnableHeaderTranslationContent |
boolean |
拖动Header的时候是否同时拖动内容(默认true) |
setEnableFooterTranslationContent |
boolean |
拖动Footer的时候是否同时拖动内容(默认true) |
setEnableAutoLoadmore |
boolean |
是否监听列表滚动到底部时触发加载事件 |
setDisableContentWhenRefresh |
boolean |
是否在刷新的时候禁止内容的一切手势操作(默认false) |
setDisableContentWhenLoading |
boolean |
是否在加载的时候禁止内容的一切手势操作(默认false) |
setReboundInterpolator |
Interpolator |
设置回弹动画的插值器 |
setRefreshHeader |
RefreshHeader |
设置指定的Header |
setRefreshFooter |
RefreshFooter |
设置指定的Footer |
setOnRefreshListener |
OnRefreshListener |
设置刷新监听器 |
setOnLoadmoreListener |
OnLoadmoreListener |
设置加载监听器 |
setOnRefreshLoadmoreListener |
OnRefreshLoadmoreListener |
同时设置上面两个监听器 |
setOnMultiPurposeListener |
OnMultiPurposeListener |
设置多功能监听器 |
setLoadmoreFinished |
boolean |
设置全部数据加载完成,之后不会触发加载事件 |
finishRefresh |
(int delayed) |
完成刷新,结束刷新动画 |
finishLoadmore |
(int delayed) |
完成加载,结束加载动画 |
getRefreshHeader |
RefreshHeader |
获取Header |
getRefreshFooter |
RefreshFooter |
获取Footer |
getState |
RefreshState |
获取当前状态 |
isRefreshing |
boolean |
是否正在刷新 |
isLoading |
boolean |
是否正在加载 |
autoRefresh |
(int delayed) |
触发自动刷新 |
autoLoadmore |
(int delayed) |
触发自动加载 |
特别说明:由于微信不支持外链,欢迎大家点击阅读原文去查看作者的文章,另外这个库的地址:https://github.com/scwang90/SmartRefreshLayout ,欢迎大家去 star 。
- .NET Core多平台开发体验[4]: Docker
- .NET Core多平台开发体验[3]: Linux (Windows Linux子系统)
- .NET Core多平台开发体验[2]: Mac OS X
- .NET Core多平台开发体验[1]: Windows
- 如何远程关闭一个ASP.NET Core应用?
- 【深度学习】谷歌deepdream原理及tensorflow实现
- 【深度学习】写诗机器人tensorflow实现
- PyTorch还是TensorFlow?这有一份新手指南
- Leetcode 300. Longest Increasing Subsequence
- Leetcode 299. Bulls and Cows
- Leetcode 297. Serialize and Deserialize Binary Tree
- Leetcode 295. Find Median from Data Stream
- 投入大见效慢,还要做AI?
- Leetcode 292. Nim Game
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法