自定义载入页 - LoadingView

依赖

implementation 'com.github.Cutta:GifView:1.4' //在项目中buildscript下添加  maven { url 'https://jitpack.io' }

xml布局

<?xml version="1.0" encoding="utf-8"?>
<com.m.k.seetaoism.widgets.MvpLoadingView xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent">


   <ImageView
       android:id="@+id/mvp_loading_iv_gif_bg_view"
       android:layout_width="100dp"
       android:layout_height="100dp"
       android:background="@drawable/mvp_loading_bg"
       android:elevation="24dp"
       app:layout_constraintBottom_toBottomOf="parent"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintStart_toStartOf="parent"
       app:layout_constraintTop_toTopOf="parent" />

   <com.cunoraz.gifview.library.GifView
       android:id="@+id/mvp_loading_gif_view"
       android:layout_width="90dp"
       android:layout_height="90dp"
       android:elevation="18dp"
       app:gif="@drawable/mvp_loading"
       app:layout_constraintBottom_toBottomOf="parent"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintStart_toStartOf="parent"
       app:layout_constraintTop_toTopOf="parent" />


   <TextView
       android:id="@+id/mvp_loading_tv_error_content"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       app:layout_constraintBottom_toBottomOf="parent"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintStart_toStartOf="parent"
       app:layout_constraintTop_toTopOf="parent"
       android:text="加载失败,请重试" />

   <Button
       android:id="@+id/mvp_loading_btn_retry"
       android:layout_width="0dp"
       android:layout_height="wrap_content"
       android:layout_marginStart="64dp"
       android:layout_marginTop="24dp"
       android:layout_marginEnd="64dp"
       android:background="@drawable/mvp_loading_retry_button_bg_selector"
       android:text="点击重试"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintStart_toStartOf="parent"
       app:layout_constraintTop_toBottomOf="@+id/mvp_loading_gif_view" />

   <ImageView
       android:id="@+id/mvp_loading_iv_error_icon"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_marginBottom="24dp"
       android:background="@drawable/mvp_loging_error"
       app:layout_constraintBottom_toTopOf="@+id/mvp_loading_gif_view"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintHorizontal_bias="0.493"
       app:layout_constraintStart_toStartOf="parent" />

   <androidx.constraintlayout.widget.Group
       android:id="@+id/mvp_loading_group_error"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:visibility="gone"
       app:constraint_referenced_ids="mvp_loading_tv_error_content,mvp_loading_btn_retry,mvp_loading_iv_error_icon" />


</com.m.k.seetaoism.widgets.MvpLoadingView>

mvp_loading_retry_button_bg_selector

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape android:layout_width="match_parent" android:layout_height="match_parent" android:shape="rectangle">
            <corners android:radius="20dp" />
            <stroke android:width="1dp" android:color="#ffffff" />
            <solid android:color="#dbdbdb" />
        </shape>

    </item>
    <item>
        <shape android:shape="rectangle">
            <corners android:radius="20dp"/>
            <stroke android:color="#dbdbdb" android:width="1dp"/>
            <solid android:color="#ffffff"/>
        </shape>
    </item>

</selector>

MvpLoadingView 类

package com.example.loadinglib;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import androidx.annotation.IntDef;
import androidx.appcompat.widget.ContentFrameLayout;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.constraintlayout.widget.ConstraintSet;
import androidx.constraintlayout.widget.Group;


import com.cunoraz.gifview.library.GifView;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

public class MvpLoadingView extends ConstraintLayout {

    public static final int MODE_POP = 1;
    public static final int MODE_FULL = 2;
    private static final int MODE_ERROR= 3;// 错误

    private ImageView mGifBackgroundView;
    private GifView mGifView;
    private Group mErrorPage;
    private ImageView mErrorIcon;
    private TextView mErrorMessage;
    private Button mRetry;

    private ViewGroup mParent;

    private OnRetryCallBack mRetryCallBack;
    private OnCancelCallBack mCancelCallBack;

    private int mCurrentMode;
    private int mPreMode;

    private boolean isEnableBackCancel; // 按返回键是否支持关闭 loading

    @Retention(RetentionPolicy.SOURCE)
    @IntDef({MODE_POP, MODE_FULL})
    public @interface LoadingMode {
    }


    public MvpLoadingView(Context context) {
        super(context);
    }

    public MvpLoadingView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

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

    @SuppressLint("ResourceType")
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        setId(10000);
        mGifBackgroundView = findViewById(R.id.mvp_loading_iv_gif_bg_view);
        mGifView = findViewById(R.id.mvp_loading_gif_view);
        mErrorPage = findViewById(R.id.mvp_loading_group_error);
        mErrorIcon = findViewById(R.id.mvp_loading_iv_error_icon);
        mErrorMessage = findViewById(R.id.mvp_loading_tv_error_content);
        mRetry = findViewById(R.id.mvp_loading_btn_retry);


        mRetry.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mRetryCallBack != null){
                    mRetryCallBack.onRetry();
                    showLoading(mPreMode);
                }
            }
        });
        setFocusableInTouchMode(true);
        requestFocus();
        setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                // 如果支持网络取消,那么关闭自己
                // 如果不支持,不拦截
                if(isEnableBackCancel){
                    if(mCancelCallBack != null){
                        mCancelCallBack.onCancel(); // 回到外面调用者去取消网络请求
                    }
                    closeLoading();
                    return true;
                }else{
                    return false;
                }
            }
        });
    }

    public void setEnableBackCancel(boolean enableBackCancel) {
        isEnableBackCancel = enableBackCancel;
    }

    public void setCancelCallBack(OnCancelCallBack cancelCallBack) {
        this.mCancelCallBack = cancelCallBack;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return false;
    }

    public void setParentContainer(ViewGroup parent) {
        mParent = parent;
    }


    public static MvpLoadingView inject(ViewGroup parent) {

        // 为了避免重复添加,那么判断一下传进来的 parent 上是否已经添加了loading view


        View child;
        for (int i = parent.getChildCount() - 1; i >= 0; i--) {
            child = parent.getChildAt(i);
            if (child instanceof MvpLoadingView) {
                return (MvpLoadingView) child;
            }
        }


        MvpLoadingView loadingView = (MvpLoadingView) LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_loading_view, parent, false);

        loadingView.setParentContainer(parent);

        return loadingView;
    }

    public void showLoading(@LoadingMode int mode) {

        if (this.getParent() == null) {

            String parentClassName = mParent.getClass().getName();
            if (parentClassName.equals(RelativeLayout.class.getName()) || parentClassName.equals(FrameLayout.class.getName()) || parentClassName.equals(ContentFrameLayout.class.getName())) {
                mParent.addView(this, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
            } else if (mParent instanceof ConstraintLayout) {

                mParent.addView(this);
                ConstraintSet constraintSet = new ConstraintSet();
                constraintSet.clone((ConstraintLayout) mParent);

                constraintSet.connect(getId(), ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START);
                constraintSet.connect(getId(), ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP);
                constraintSet.connect(getId(), ConstraintSet.END, mParent.getId(), ConstraintSet.END);
                constraintSet.connect(getId(), ConstraintSet.BOTTOM, mParent.getId(), ConstraintSet.BOTTOM);
                constraintSet.applyTo((ConstraintLayout) mParent);


            }
        }



        if(mCurrentMode == mode){
            return;
        }


        mPreMode = mCurrentMode;

        mCurrentMode = mode;

        mErrorPage.setVisibility(GONE);
        if (mode == MODE_POP) {
            setBackgroundColor(Color.TRANSPARENT);
            mGifBackgroundView.setVisibility(VISIBLE);
        } else {
            setBackgroundColor(Color.WHITE);
            mGifBackgroundView.setVisibility(GONE);
        }
        mGifView.setVisibility(VISIBLE);
        mGifView.play();

}

    public void onError(){
        onError("加载失败,请重试",null);
    }

    public void onError(OnRetryCallBack onRetryCallBack){
        onError("加载失败,请重试",onRetryCallBack);
    }

    public void onError(String errMessage,OnRetryCallBack onRetryCallBack){

        mRetryCallBack = onRetryCallBack;
        mGifView.pause();
        mGifView.setVisibility(GONE);
        mGifBackgroundView.setVisibility(GONE);

        mErrorPage.setVisibility(VISIBLE);

        if(mCurrentMode != MODE_FULL){
            setBackgroundColor(Color.WHITE);
        }
        mErrorMessage.setText(errMessage);
        mRetry.setVisibility(mRetryCallBack == null ? GONE : VISIBLE);

        mPreMode = mCurrentMode;

        mCurrentMode = MODE_ERROR;
    }


    public void closeLoading() {
        if (mParent != null) {
            mParent.removeView(this);
        }
    }


    public interface OnRetryCallBack{
        void onRetry();
    }
    public interface OnCancelCallBack{
        void onCancel();
    }
}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342