1.添加依赖
implementation ‘com.scwang.smartrefresh:SmartRefreshLayout:1.0.3’
implementation ‘com.scwang.smartrefresh:SmartRefreshHeader:1.0.3’
2.自定义头部
public class MRefreshHeader extends LinearLayout implements RefreshHeader {
private ImageView mImage;
// private AnimationDrawable mAnimPull;
// private AnimationDrawable mAnimRefresh;
private Animation mAnimRefresh,mAnimPull;
/**
* 1,构造方法
*/
public MRefreshHeader(Context context) {
this(context, null, 0);
}
public MRefreshHeader(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public MRefreshHeader(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
View view = View.inflate(context, R.layout.m_refresh_header, this);
mImage = view.findViewById(R.id.iv_refresh_header);
}
/**
* 2,获取真实视图(必须返回,不能为null)一般就是返回当前自定义的view
*/
@NonNull
@Override
public View getView() {
return this;
}
/**
* 3,获取变换方式(必须指定一个:平移、拉伸、固定、全屏),Translate指平移,大多数都是平移
*/
@NonNull
@Override
public SpinnerStyle getSpinnerStyle() {
return SpinnerStyle.Translate;
}
/**
* 4,执行下拉的过程
*
* @param percent
* @param offset
*/
@Override
public void onPullingDown(float percent, int offset, int headerHeight, int extendHeight) {
if (percent < 1) {
mImage.setScaleX(percent);
mImage.setScaleY(percent);
}
}
/**
* 5,一般可以理解为一下case中的三种状态,在达到相应状态时候开始改变
* 注意:这三种状态都是初始化的状态
*/
@Override
public void onStateChanged(@NonNull RefreshLayout refreshLayout, @NonNull RefreshState oldState, @NonNull RefreshState newState) {
switch (newState) {
//1,下拉刷新的开始状态:下拉可以刷新
case PullDownToRefresh:
mImage.setImageResource(R.drawable.icon_refresh_line_loading_black);
break;
//2,下拉到最底部的状态:释放立即刷新
case ReleaseToRefresh:
// mImage.setImageResource(R.drawable.anim_pull_end);
// mAnimPull = (AnimationDrawable) mImage.getDrawable();
// mAnimPull.start();
mImage.setImageResource(R.drawable.icon_refresh_line_loading_black);
break;
//3,下拉到最底部后松手的状态:正在刷新
case Refreshing:
// mImage.setImageResource(R.drawable.anim_pull_refreshing);
// mAnimRefresh = (AnimationDrawable) mImage.getDrawable();
// mAnimRefresh.start();
mImage.setImageResource(R.drawable.icon_refresh_line_loading_black);
mAnimRefresh = new RotateAnimation(0f, 360f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
//ani.setFillAfter(boolean); true停留在旋转后的位置 false复位
mAnimRefresh.setFillAfter(!mAnimRefresh.getFillAfter());
mAnimRefresh.setDuration(500);
mAnimRefresh.setRepeatCount(Animation.INFINITE);
mImage.startAnimation(mAnimRefresh);
break;
default:
}
}
/**
* 6,结束下拉刷新的时候需要关闭动画
*
* @param refreshLayout
* @param success
* @return
*/
@Override
public int onFinish(@NonNull RefreshLayout refreshLayout, boolean success) {
// if (mAnimRefresh != null && mAnimRefresh.isRunning()) {
// mAnimRefresh.stop();
// }
// if (mAnimPull != null && mAnimPull.isRunning()) {
// mAnimPull.stop();
// }
if (mAnimRefresh != null && mAnimRefresh.hasStarted()) {
mAnimRefresh.cancel();
}
if (mAnimPull != null && mAnimPull.hasStarted()) {
mAnimPull.cancel();
}
return 0;
}
@Override
public void onReleasing(float percent, int offset, int headerHeight, int extendHeight) {
}
@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 onHorizontalDrag(float percentX, int offsetX, int offsetMax) {
}
@Override
public boolean isSupportHorizontalDrag() {
return false;
}
}
头部xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:background="@color/white"
android:padding="5dp"
android:gravity="center"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/iv_refresh_header"
android:scaleX="0"
android:scaleY="0"
android:translationY="0dp"
android:layout_width="24dip"
android:layout_height="24dip" />
</LinearLayout>
3自定义尾部
public class MRefreshFooter extends LinearLayout implements RefreshFooter {
private ImageView mImage;
private Animation mAnim;
public MRefreshFooter(Context context) {
this(context, null, 0);
}
public MRefreshFooter(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public MRefreshFooter(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
View view = View.inflate(context, R.layout.m_refresh_footer, this);
mImage = view.findViewById(R.id.iv_refresh_footer);
mAnim = AnimationUtils.loadAnimation(getContext(), R.anim.anim_round_rotate);
LinearInterpolator linearInterpolator = new LinearInterpolator();
mAnim.setInterpolator(linearInterpolator);
}
@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) {
//控制是否稍微上滑动就刷新
kernel.getRefreshLayout().setEnableAutoLoadmore(false);
}
@Override
public void onPullingUp(float percent, int offset, int footerHeight, int extendHeight) {
}
@Override
public void onPullReleasing(float percent, int offset, int footerHeight, int extendHeight) {
}
@Override
public boolean setLoadmoreFinished(boolean finished) {
return false;
}
@Override
public void onStartAnimator(@NonNull RefreshLayout refreshLayout, int height, int maxDragHeight) {
}
@Override
public int onFinish(@NonNull RefreshLayout refreshLayout, boolean success) {
if(mAnim != null && mAnim.hasStarted() && !mAnim.hasEnded()){
mAnim.cancel();
mImage.clearAnimation();
}
return 0;
}
@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 PullToUpLoad:
if (mAnim != null) {
mImage.startAnimation(mAnim);
}
break;
case Loading:
case LoadFinish:
break;
case ReleaseToLoad:
break;
default:
}
}
}
尾部xml
<?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="wrap_content"
android:background="@color/white"
android:gravity="center"
android:orientation="vertical"
android:padding="5dp">
<ImageView
android:id="@+id/iv_refresh_footer"
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@drawable/icon_refresh_line_loading_black" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="底部"
android:textSize="11sp" />
</LinearLayout>
4.使用示例
<?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"
android:background="@android:color/white"
android:orientation="vertical">
<View
android:id="@+id/fuzhu_line_v"
android:layout_width="match_parent"
android:layout_height="0.1dp" />
<com.scwang.smartrefresh.layout.SmartRefreshLayout
android:id="@+id/content_sfl"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white">
<com.xxxx.xxx.xxx.MRefreshHeader
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/content_rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white" />
<com.xxx.xxx.xxx.MRefreshFooter
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.scwang.smartrefresh.layout.SmartRefreshLayout>
</LinearLayout>
示例资源图片: