Android自定义SmartRefreshLayout下拉刷新Header和上拉加载Footer

废话不多说,先看效果图;

1.这是默认效果(一般情况可以满足需求。但如果需要自定义时,就无法处理了。) SmartRefreshLayout框架,提供了部分刷新动画,但个人认为针对列表刷新动画来说,所提供的的动画不适合。所以还需要自己处理。

在这里插入图片描述

2.这是自定义效果(如果需要有自己的动画就要自定义,动画自己添加进去图片即可。)

在这里插入图片描述

上图的刷新动画图集是由39张图片组成的帧动画;下拉刷新是由34个图片组成的帧动画。(图片我就不一一贴出来了,如果需要请下载源码中获取)。

SmartRefreshLayout框架(github上很火的一个刷新框架)
(地址:https://github.com/scwang90/SmartRefreshLayout

特点:强大,稳定,成熟的下拉刷新框架;炫酷、多样、实用、美观的Header和Footer;

功能:

  1. 支持横向刷新,支持多点触摸,支持AndroidX
  2. 支持 Header 和 Footer 交换混用,支持淘宝二楼和二级刷新
  3. 支持所有可滚动视图的越界回弹, 支持嵌套多层的视图结构
  4. 支持设多种滑动方式:平移、拉伸、背后固定、顶层固定、全屏
  5. 支持所有的 View(AbsListView、RecyclerView、WebView…View)
  6. 支持自定义并且已经集成了很多炫酷的 Header 和 Footer.
  7. 支持和 ListView 的无缝同步滚动 和 CoordinatorLayout 的嵌套滚动 .
  8. 支持自动刷新、自动上拉加载(自动检测列表惯性滚动到底部,而不用手动上拉).
  9. 支持自定义回弹动画的插值器,实现各种炫酷的动画效果等等…
如果需要,希望能够帮助到你。
下面开始上代码。
  • 第一步,自定义SmartRefreshLayout
import android.content.Context;
import android.util.AttributeSet;
import android.view.ViewGroup;
import com.scwang.smart.refresh.layout.SmartRefreshLayout;

/**
 * @author mr.cc
 * created at  2020/12/22 16:45
 * discroption
 */
public class MySmartRefreshLayout extends SmartRefreshLayout {

    MyHeaderView mHeaderView;

    public MySmartRefreshLayout (Context context) {
        this(context, null);
    }

    public MySmartRefreshLayout (Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MySmartRefreshLayout (Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs);

        ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);
        mHeaderView= new MyHeaderView(context);
        mHeaderView.setLayoutParams(layoutParams);
        addView(mHeaderView, 0);
    }

}
注:其中的MyHeaderView 为自定义刷新头。
  • 第二步:自定义MyHeaderView
import android.content.Context;
import android.graphics.drawable.AnimationDrawable;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import com.scwang.smart.refresh.layout.api.RefreshLayout;
import com.scwang.smart.refresh.layout.constant.RefreshState;
import com.scwang.smart.refresh.layout.simple.SimpleComponent;

/**
 * @author mr.cc
 * created at  2020/12/22 16:46
 * discroption
 */
public class MyHeaderView extends SimpleComponent {

    public static String REFRESH_HEADER_PULLING = "下拉可以刷新";//"下拉可以刷新";
    public static String REFRESH_HEADER_LOADING = "正在加载...";//"正在加载...";
    public static String REFRESH_HEADER_RELEASE = "释放立即刷新";
    public static String REFRESH_HEADER_FINISH = "刷新成功";//"刷新完成";
    public static String REFRESH_HEADER_FAILED = "刷新失败";//"刷新失败";

//    private TextView mTitleText;

    AnimationDrawable animDrawable;

    public MyHeaderView(Context context) {
        this(context, null);
    }

    public MyHeaderView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyHeaderView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        View view = LayoutInflater.from(context).inflate(R.layout.miyuan_refresh_head, this);
        ImageView ref_head_img = view.findViewById(R.id.ref_head_img);
        animDrawable = (AnimationDrawable) getResources().getDrawable(R.drawable.my_refresh_head);
        ref_head_img.setImageDrawable(animDrawable);

//        mTitleText = view.findViewById(R.id.txt);

    }

    @Override
    public int onFinish(@NonNull RefreshLayout layout, boolean success) {
        if (success) {
//            mTitleText.setText(REFRESH_HEADER_FINISH);
            animDrawable.stop();
        } else {
            animDrawable.stop();
//            mTitleText.setText(REFRESH_HEADER_FAILED);
        }
        super.onFinish(layout, success);
        return 500; //延迟500毫秒之后再弹回
    }

    @Override
    public void onStateChanged(@NonNull RefreshLayout refreshLayout, @NonNull RefreshState oldState, @NonNull RefreshState newState) {
        switch (newState) {
            case PullDownToRefresh: //下拉过程
//                mTitleText.setText(REFRESH_HEADER_PULLING);
                animDrawable.start();
                break;
            case ReleaseToRefresh: //松开刷新
//                mTitleText.setText(REFRESH_HEADER_RELEASE);
                break;
            case Refreshing: //loading中
//                mTitleText.setText(REFRESH_HEADER_LOADING);
                break;
        }
    }
}
  • 第三步,在layout里面新建一个layout,命名为miyuan_refresh_head,视为刷新头布局。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:layout_width="match_parent"
    android:layout_height="60dp"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:gravity="center|center_vertical"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/ref_head_img"
        android:layout_width="wrap_content"
        android:layout_height="60dp"
        android:src="@mipmap/loading_36"/>

</LinearLayout>
  • 第四步:在drawable里面新增一个文件,命名为my_refresh_head,视为刷新的动画。
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false" >
    <item android:drawable="@mipmap/loading_1" android:duration="50"/>
    <item android:drawable="@mipmap/loading_2" android:duration="50"/>
    <item android:drawable="@mipmap/loading_3" android:duration="50"/>
    <item android:drawable="@mipmap/loading_4" android:duration="50"/>
    <item android:drawable="@mipmap/loading_5" android:duration="50"/>
    <item android:drawable="@mipmap/loading_6" android:duration="50"/>
    <item android:drawable="@mipmap/loading_7" android:duration="50"/>
    <item android:drawable="@mipmap/loading_8" android:duration="50"/>
    <item android:drawable="@mipmap/loading_9" android:duration="50"/>
    <item android:drawable="@mipmap/loading_10" android:duration="50"/>
    <item android:drawable="@mipmap/loading_11" android:duration="50"/>
    <item android:drawable="@mipmap/loading_12" android:duration="50"/>
    <item android:drawable="@mipmap/loading_13" android:duration="50"/>
    <item android:drawable="@mipmap/loading_14" android:duration="50"/>
    <item android:drawable="@mipmap/loading_15" android:duration="50"/>
    <item android:drawable="@mipmap/loading_16" android:duration="50"/>
    <item android:drawable="@mipmap/loading_17" android:duration="50"/>
    <item android:drawable="@mipmap/loading_18" android:duration="50"/>
    <item android:drawable="@mipmap/loading_19" android:duration="50"/>
    <item android:drawable="@mipmap/loading_20" android:duration="50"/>
    <item android:drawable="@mipmap/loading_21" android:duration="50"/>
    <item android:drawable="@mipmap/loading_22" android:duration="50"/>
    <item android:drawable="@mipmap/loading_23" android:duration="50"/>
    <item android:drawable="@mipmap/loading_24" android:duration="50"/>
    <item android:drawable="@mipmap/loading_25" android:duration="50"/>
    <item android:drawable="@mipmap/loading_26" android:duration="50"/>
    <item android:drawable="@mipmap/loading_27" android:duration="50"/>
    <item android:drawable="@mipmap/loading_28" android:duration="50"/>
    <item android:drawable="@mipmap/loading_29" android:duration="50"/>
    <item android:drawable="@mipmap/loading_30" android:duration="50"/>
    <item android:drawable="@mipmap/loading_31" android:duration="50"/>
    <item android:drawable="@mipmap/loading_32" android:duration="50"/>
    <item android:drawable="@mipmap/loading_33" android:duration="50"/>
    <item android:drawable="@mipmap/loading_34" android:duration="50"/>
    <item android:drawable="@mipmap/loading_35" android:duration="50"/>
    <item android:drawable="@mipmap/loading_36" android:duration="50"/>
    <item android:drawable="@mipmap/loading_37" android:duration="50"/>
    <item android:drawable="@mipmap/loading_38" android:duration="50"/>
    <item android:drawable="@mipmap/loading_39" android:duration="50"/>
</animation-list>
注:@mipmap/loading_1为刷新真图片。

至此,自定义刷新功能已经完成,自定义加载功能与自定义刷新功能一样。下面给出代码:

  • 第一步:自定义加载功能如下:
import android.content.Context;
import android.graphics.drawable.AnimationDrawable;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.scwang.smart.refresh.layout.api.RefreshLayout;
import com.scwang.smart.refresh.layout.constant.RefreshState;
import com.scwang.smart.refresh.layout.simple.SimpleComponent;

/**
 * 自定义FooterView
 */
public class MyFooterView extends SimpleComponent {

    AnimationDrawable animDrawable;

    static TextView srl_classics_title;
    static ImageView ref_foot_img;
    public MyFooterView(Context context) {
        this(context, null);
    }

    public MyFooterView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyFooterView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        View view = LayoutInflater.from(context).inflate(R.layout.miyuan_refresh_footer, this);
        ref_foot_img = view.findViewById(R.id.ref_foot_img);
        srl_classics_title = view.findViewById(R.id.srl_classics_title);
        animDrawable = (AnimationDrawable) getResources().getDrawable(R.drawable.my_refresh_foot);
        ref_foot_img.setImageDrawable(animDrawable);
        animDrawable.start();
    }

    @Override
    public int onFinish(@NonNull RefreshLayout layout, boolean success) {
        if (success) {
//            mTitleText.setText(REFRESH_HEADER_FINISH);
        } else {
//            mTitleText.setText(REFRESH_HEADER_FAILED);
        }
        super.onFinish(layout, success);
        return 500; //延迟500毫秒之后再弹回
    }

    @Override
    public void onStateChanged(@NonNull RefreshLayout refreshLayout, @NonNull RefreshState oldState, @NonNull RefreshState newState) {
    }

    protected static boolean mNoMoreData = false;

    public static void setmNoMoreData(boolean noMoreData){
        mNoMoreData = noMoreData;
        if(mNoMoreData){
            ref_foot_img.setVisibility(GONE);
            srl_classics_title.setVisibility(VISIBLE);
            srl_classics_title.setText("我也是有底线的~");
        }else{
            ref_foot_img.setVisibility(VISIBLE);
            srl_classics_title.setVisibility(GONE);
            srl_classics_title.setText("正在加载,别慌嘛~");
        }
        mNoMoreData = false;
    }

    @Override
    public boolean setNoMoreData(boolean noMoreData) {
        Log.i("noMoreData", "noMoreData=" + noMoreData);
        return true;
    }

    /**
     * 设置数据全部加载完成,将不能再次触发加载功能
     */
//    @Override
//    public boolean setNoMoreData(boolean noMoreData) {
//        if (mNoMoreData != noMoreData) {
//            mNoMoreData = noMoreData;
//            if (noMoreData) {
//                ref_foot_img.setVisibility(GONE);
//                srl_classics_title.setVisibility(VISIBLE);
//                srl_classics_title.setText("我也是有底线的~");
//            } else {
//                srl_classics_title.setText("正在加载,别慌嘛~");
                srl_classics_title.setVisibility(GONE);
//            }
//        }
//        return true;
//    }

}
  • 第二步:在layout里面新建一个layout,命名为miyuan_refresh_footer,视为加载头布局。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:layout_width="match_parent"
    android:layout_height="60dp"
    xmlns:android="http://schemas.android.com/apk/res/android">

    <ImageView
        android:id="@+id/ref_foot_img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:src="@mipmap/two_loading00"/>

    <TextView
        android:id="@+id/srl_classics_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:maxLines="1"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"
        android:gravity="center"
        android:textColor="#000000"
        android:textSize="18dp"/>

</RelativeLayout>
  • 第三步:在drawable里面新增一个文件,命名为my_refresh_foot,视为加载的动画。
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false" >
    <item android:drawable="@mipmap/two_loading00" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading01" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading02" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading03" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading04" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading05" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading06" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading07" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading08" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading09" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading10" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading11" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading12" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading13" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading14" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading15" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading16" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading17" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading18" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading19" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading20" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading21" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading22" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading23" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading24" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading25" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading26" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading27" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading28" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading29" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading30" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading31" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading32" android:duration="50"/>
    <item android:drawable="@mipmap/two_loading33" android:duration="50"/>
</animation-list>

到这,加载也就完了。如何使用呢,请继续往下看:

到这一步,所有的自定义代码都已经结束,使用方法也很简单,推荐在界面activity_main布局中直接使用即可。

<cszs.sanhua.com.testsmartdemo.MySmartRefreshLayout
        android:id="@+id/fragment_one_refreshlayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:srlEnablePreviewInEditMode="true"
        app:srlEnableFooterFollowWhenLoadFinished="true"
        app:srlEnableLoadMoreWhenContentNotFull="false"
        app:srlEnableFooterFollowWhenNoMoreData="true">

        <android.support.v4.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">

                <ImageView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:scaleType="fitXY"
                    android:adjustViewBounds="true"
                    android:src="@mipmap/ic_launcher"/>

                <ImageView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:scaleType="fitXY"
                    android:adjustViewBounds="true"
                    android:src="@mipmap/ic_launcher"/>

                <ImageView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:scaleType="fitXY"
                    android:adjustViewBounds="true"
                    android:src="@mipmap/ic_launcher"/>

                <ImageView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:scaleType="fitXY"
                    android:adjustViewBounds="true"
                    android:src="@mipmap/ic_launcher"/>

            </LinearLayout>

        </android.support.v4.widget.NestedScrollView>

        <cszs.sanhua.com.testsmartdemo.MyFooterView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:srlAccentColor="#000000"/>

    </cszs.sanhua.com.testsmartdemo.MySmartRefreshLayout>

大功告成,因为自定义加载这块的回调处理的还是有一点问题,所以在使用的时候有一点地方需要注意,请在MyFooterView 里面认真阅读注释。

以上就是所有的代码

附上demo源码。

源码:源码请点这里…


q:486789970
email:[email protected]

如果有什么问题,欢迎大家指导。并相互联系,希望能够通过文章互相学习。

											                               	---财财亲笔

Guess you like

Origin blog.csdn.net/qq_35840038/article/details/105580211