Android下拉刷新的实现(二) - PtrFrameLayout篇
👉关于作者
已经工作三年的95后程序员,坐标上海。平时在公司写Android原生App,业务时间会抽空学习Java后端,目标是成为全栈工程师,志同道合的可以私我聊聊haha。加入优快云快4年了,看了很多优秀作者的博客收获很多。后面的时间里,我写也会整理总结一些工作中使用到的知识分享出来。我的座右铭:人生在勤,不索何获。大家一起努力加油吧
👉正文部分
Android下拉刷新的实现系列文章准备了两篇,对应SwipeRefreshLayou和PtrFrameLayout。SwipeRefreshLayout作为Android原生的下拉刷新控件,UI效果比较简洁,也比较容易开发,但是实现的效果过于简单,对于提升页面的美观度有着局限性;PtrFrameLayout是一款下拉刷新框架,提供的UI效果比较好,复杂度也会高一点,大家可以按照自己的实际情况来进行选择
1、实现效果
2、Gradle引用
implementation 'in.srain.cube:ultra-ptr:1.0.11'
3、具体实现
1、xml布局,将需要刷新的组件嵌套到PtrFrameLayout中
关于PtrFrameLayout的属性,设置的还比较多,但是不是很重要,这里可以暂时跳过,一会我再补充这些属性的作用
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:cube_ptr="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".recyclerview.PtrFrameLayoutDemoActivity">
<in.srain.cube.views.ptr.PtrFrameLayout
android:id="@+id/ptr_frame_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
cube_ptr:ptr_resistance="1.7"
cube_ptr:ptr_ratio_of_header_height_to_refresh="1.2"
cube_ptr:ptr_duration_to_close="300"
cube_ptr:ptr_duration_to_close_header="2000"
cube_ptr:ptr_keep_header_when_refresh="true"
cube_ptr:ptr_pull_to_fresh="false">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</in.srain.cube.views.ptr.PtrFrameLayout>
</RelativeLayout>
2、findViewById
PtrFrameLayout ptrFrameLayout = findViewById(R.id.ptr_frame_layout);
3、设置Loading的布局,因为Loading在顶部,所以使用setHeaderView方法设置
HeaderView的XML布局
<?xml version="1.0" encoding="utf-8"?>
<ProgressBar
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/header"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_centerHorizontal="true"
android:layout_margin="10dp" />
加载HeaderView
View root = LayoutInflater.from(this).inflate(R.layout.ptr_frame_header, ptrFrameLayout, false);
View header = root.findViewById(R.id.header);
设置HeaderView
ptrFrameLayout.setHeaderView(header);
4、设置事件监听器,对应两个回调,一个用来设置下拉的条件,一个在下拉开始的时候调用
ptrFrameLayout.setPtrHandler(new PtrHandler() {
//该方法用来设置下拉的条件
@Override
public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {
//如果content也就是我们的内容组件不能下滑,就可以进行下拉刷新
return !content.canScrollVertically(-1);
}
//该方法在下拉开始的时候调用
@Override
public void onRefreshBegin(final PtrFrameLayout frame) {
//设置一个两秒钟后完成刷新的动作
handler.postDelayed(new Runnable() {
@Override
public void run() {
//设置刷新已完成,也就会关闭Loading
frame.refreshComplete();
}
},2000);
}
});
5、设置UI监听器,主要关注开始刷新的回调,以及刷新结束的回调
ptrFrameLayout.addPtrUIHandler(new PtrUIHandler() {
@Override
public void onUIReset(PtrFrameLayout frame) {
}
@Override
public void onUIRefreshPrepare(PtrFrameLayout frame) {
}
//开始刷新的回调
@Override
public void onUIRefreshBegin(PtrFrameLayout frame) {
//设置HeaderView(ProgressBar)开始转动
if (frame.getHeaderView()!=null && frame.getHeaderView() instanceof ProgressBar){
((ProgressBar)frame.getHeaderView()).setIndeterminate(true);
}
}
//刷新结束的回调
@Override
public void onUIRefreshComplete(PtrFrameLayout frame) {
//设置HeaderView(ProgressBar)停止转动
if (frame.getHeaderView()!=null && frame.getHeaderView() instanceof ProgressBar){
((ProgressBar)frame.getHeaderView()).setIndeterminate(false);
}
}
@Override
public void onUIPositionChange(PtrFrameLayout frame, boolean isUnderTouch, byte status, PtrIndicator ptrIndicator) {
}
});
5、到这里也就完成了基本的设置,一开始的预览效果也就会实现了
4、关于PtrFrameLayout的属性说明
//有6个参数可配置:
//阻尼系数
//默认: 1.7f,越大,感觉下拉时越吃力。
cube_ptr:ptr_resistance="1.7"
//触发刷新时移动的位置比例
//默认,1.2f,移动达到头部高度1.2倍时可触发刷新操作。
cube_ptr:ptr_ratio_of_header_height_to_refresh="1.2"
//回弹延时
//默认 200ms,回弹到刷新高度所用时间
cube_ptr:ptr_duration_to_close="300"
//头部回弹时间
//默认1000ms
cube_ptr:ptr_duration_to_close_header="2000"
//刷新时保持头部
//默认值 true.
cube_ptr:ptr_keep_header_when_refresh="true"
//下拉刷新 / 释放刷新
//默认为释放刷新
cube_ptr:ptr_pull_to_fresh="false"