引入依赖
在app的build.gradle 引入
implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0'
implementation 'com.scwang.smartrefresh:SmartRefreshHeader:1.1.0'//没有使用特殊Header,可以不加这行
implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.50'
还需要在本文件加入
allprojects {
repositories {
...
maven { url "https://jitpack.io" }
}
}
自定义头部尾部
由于smartRefreshLayout 自带的头部尾部一般不适合应用于自己的项目中,那么我们就需要自定义头部尾部View。
自定义头部View
/**
* Created by yangyang on 2022/10/14.
*/
public class MyRefreshHeader extends LinearLayout implements RefreshHeader {
private final ImageView ivHeader;
private final TextView headText;
private Animation mAnimRefresh;
/**
* 1,构造方法
*/
public MyRefreshHeader(Context context) {
this(context, null, 0);
}
public MyRefreshHeader(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public MyRefreshHeader(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
View view = View.inflate(context, R.layout.refresh_header_view, this);
ivHeader = view.findViewById(R.id.iv_refresh_header);
headText = view.findViewById(R.id.tv_header);
}
/**
* 2,获取真实视图(必须返回,不能为null)一般就是返回当前自定义的view
*/
@NonNull
@Override
public View getView() {
return this;
}
/**
* 3,获取变换方式(必须指定一个:平移、拉伸、固定、全屏),Translate指平移,大多数都是平移
*/
@NonNull
@Override
public SpinnerStyle getSpinnerStyle() {
return SpinnerStyle.Translate;
}
/**
* 4,一般可以理解为一下case中的三种状态,在达到相应状态时候开始改变
* 注意:这三种状态都是初始化的状态
*/
@Override
public void onStateChanged(@NonNull RefreshLayout refreshLayout, @NonNull RefreshState oldState, @NonNull RefreshState newState) {
switch (newState) {
case None:
case PullDownToRefresh:
ivHeader.setImageResource(R.mipmap.ic_launcher);
headText.setText("下拉开始刷新");
break;
case Refreshing:
headText.setText("正在刷新...");
ivHeader.setImageResource(R.mipmap.ic_launcher);
mAnimRefresh = new RotateAnimation(0f, 360f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
mAnimRefresh.setFillAfter(!mAnimRefresh.getFillAfter());
mAnimRefresh.setDuration(500);
mAnimRefresh.setRepeatCount(Animation.INFINITE);
ivHeader.startAnimation(mAnimRefresh);
break;
case ReleaseToRefresh:
headText.setText("释放立即刷新");
ivHeader.setImageResource(R.mipmap.ic_launcher);
break;
default:
}
}
/**
* 5,结束下拉刷新的时候需要关闭动画
*
* @param refreshLayout
* @param success
* @return
*/
@Override
public int onFinish(@NonNull RefreshLayout refreshLayout, boolean success) {
if (mAnimRefresh != null && mAnimRefresh.hasStarted()) {
mAnimRefresh.cancel();
}
if (success) {
headText.setText("刷新完成");
} else {
headText.setText("刷新失败");
}
return 200;
}
@Override
public void onStartAnimator(@NonNull RefreshLayout refreshLayout, int height, int maxDragHeight) {
}
@Override
public void setPrimaryColors(int... colors) {
}
@Override
public void onInitialized(@NonNull RefreshKernel kernel, int height, int maxDragHeight) {
}
@Override
public void onMoving(boolean isDragging, float percent, int offset, int height, int maxDragHeight) {
}
@Override
public void onReleased(@NonNull RefreshLayout refreshLayout, int height, int maxDragHeight) {
}
@Override
public void onHorizontalDrag(float percentX, int offsetX, int offsetMax) {
}
@Override
public boolean isSupportHorizontalDrag() {
return false;
}
}
refresh_header_view 布局文件
这里的动画效果可以根据自己项目的实际需要来修改,上面代码是图片旋转360度。这里也可以用Glide加载动态图,这个看自己的喜好,实现方式有很多种。(附效果图用的是Glide加载的动图)。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:background="@color/white"
android:orientation="vertical"
android:padding="5dp"
android:gravity="center"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/iv_refresh_header"
android:translationY="0dp"
android:layout_height="40dp"
android:layout_width="40dp"/>
<TextView
android:id="@+id/tv_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"/>
</LinearLayout>
自定义尾部View
public class MyRefreshFooter extends LinearLayout implements RefreshFooter {
private final TextView tvFooter;
private final ProgressBar progressBar;
public MyRefreshFooter(Context context) {
this(context, null, 0);
}
public MyRefreshFooter(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public MyRefreshFooter(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
View view = View.inflate(context, R.layout.refresh_footer_view, this);
tvFooter = view.findViewById(R.id.tv_footer);
progressBar = view.findViewById(R.id.progressBar);
}
@NonNull
@Override
public View getView() {
return this;
}
@NonNull
@Override
public SpinnerStyle getSpinnerStyle() {
return SpinnerStyle.Translate;
}
@Override
public void setPrimaryColors(int... colors) {
}
@Override
public void onInitialized(@NonNull RefreshKernel kernel, int height, int maxDragHeight) {
}
@Override
public void onMoving(boolean isDragging, float percent, int offset, int height, int maxDragHeight) {
}
@Override
public void onReleased(@NonNull RefreshLayout refreshLayout, int height, int maxDragHeight) {
}
@Override
public void onStartAnimator(@NonNull RefreshLayout refreshLayout, int height, int maxDragHeight) {
}
@Override
public int onFinish(@NonNull RefreshLayout refreshLayout, boolean success) {
progressBar.setVisibility(View.GONE);
if (success) {
tvFooter.setText("加载完成");
} else {
tvFooter.setText("加载失败");
}
return 200;
}
@Override
public void onHorizontalDrag(float percentX, int offsetX, int offsetMax) {
}
@Override
public boolean isSupportHorizontalDrag() {
return false;
}
@Override
public void onStateChanged(@NonNull RefreshLayout refreshLayout, @NonNull RefreshState oldState, @NonNull RefreshState newState) {
switch (newState) {
case None:
case Loading:
progressBar.setVisibility(View.VISIBLE);
tvFooter.setText("正在加载");
break;
case PullUpToLoad:
progressBar.setVisibility(View.GONE);
tvFooter.setText("已全部加载完毕");
break;
}
}
@Override
public boolean setNoMoreData(boolean noMoreData) {
return false;
}
}
跟头部很类似,动画效果可以按自己项目需求修改,我的是文字后面加了ProgressBar。
refresh_footer_view 布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="30dp"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_footer"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/transparent"
android:indeterminateBehavior="repeat"
android:indeterminateDrawable="@drawable/progressbar_style"
android:indeterminateDuration="2" />
</LinearLayout>
progressbar_style 文件代码
<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360">
<shape
android:innerRadius="8dp"
android:thickness="3dp"
android:shape="ring"
android:useLevel="false">
<gradient
android:centerY="0.50"
android:endColor="#cccccc"
android:startColor="@color/white"
android:type="sweep"
android:useLevel="false" />
</shape>
</animated-rotate>
至此一个简单好用的SmartRefreshLayout的头部尾部就好了。
使用
public class SmartRefreshLayoutActivity extends BaseActivity {
SmartRefreshLayout smartRefreshLayout;
RecyclerView recyclerView;
MyAdapter adapter;
List<String> dataList = new ArrayList<>();
@Override
protected int initLayout() {
return R.layout.activity_smart_refresh;
}
@Override
protected void initView() {
setTitle("SmartRefreshLayout自定义头尾部");
finishActivity();
smartRefreshLayout = findViewById(R.id.smartLayout);
smartRefreshLayout.setRefreshHeader(new MyRefreshHeader(this));
smartRefreshLayout.setRefreshFooter(new MyRefreshFooter(this));
recyclerView = findViewById(R.id.recycleView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new MyAdapter(dataList);
recyclerView.setAdapter(adapter);
setData();
}
@Override
protected void initData() {
smartRefreshLayout.setOnLoadMoreListener(refreshlayout -> {
new Handler().postDelayed(() -> {
setData();
refreshlayout.finishLoadMoreWithNoMoreData();
}, 500);
});
smartRefreshLayout.setOnRefreshListener(refreshlayout -> {
new Handler().postDelayed(() -> {
dataList.clear();
setData();
refreshlayout.finishRefresh(); // TODO
}, 500);
});
}
private void setData() {
dataList.add("1");
dataList.add("2");
dataList.add("3");
dataList.add("4");
dataList.add("5");
dataList.add("6");
adapter.setNewData(dataList);
}
}
布局文件activity_smart_refresh
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical">
<include
android:id="@+id/lin"
layout="@layout/base_title" />
<com.scwang.smartrefresh.layout.SmartRefreshLayout
android:id="@+id/smartLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycleView"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:itemCount="3"/>
</com.scwang.smartrefresh.layout.SmartRefreshLayout>
</LinearLayout>
MyAdapter代码
public class MyAdapter extends BaseQuickAdapter<String, BaseViewHolder> {
private List<String> datas=new ArrayList<>();
public MyAdapter(@Nullable List<String> data) {
super(R.layout.list_item, data);
}
@Override
protected void convert(@NonNull BaseViewHolder helper, String item) {
helper.setText(R.id.tv,item);
}
}
布局文件list_item
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_margin="10dp"
android:background="#00FFFF"
android:gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1"
android:textColor="#ffffff"
android:textSize="16sp" />
</LinearLayout>
附效果图