Android 多状态布局

无侵入性实现, 不需要每一个布局都引入多状态布局

先上图

1.多状态View的编写

java代码

package com.mir.datepicker;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.annotation.IntDef;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

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

/**
 * @data 2018-08-01
 * @desc
 */

public class StatusLayout extends RelativeLayout {

    public static final int STATUS_LOADING = 1;
    public static final int STATUS_LOAD_FAIL = 2;
    public static final int STATUS_HIDE = 3;
    private int mStatus = STATUS_LOADING;

    @IntDef({STATUS_LOADING, STATUS_LOAD_FAIL, STATUS_HIDE})
    @Retention(RetentionPolicy.SOURCE)
    @interface Status{}

    private Context mContext;
    private FrameLayout mFlFailContainer;
    private LinearLayout mLlLoading;
    private TextView mTvFailMsg;

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

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

    public StatusLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        initView();
    }

    private void initView() {
        LayoutInflater.from(mContext).inflate(R.layout.layout_status, this, true);
        mFlFailContainer = findViewById(R.id.fl_fail_container);
        mLlLoading = findViewById(R.id.ll_loading);
        mTvFailMsg = findViewById(R.id.tv_fail_msg);
    }

    /**
     * 设置多状态布局状态
     * @param status @param status {@link Status}
     */
    public void setStatus(@Status int status){
        this.mStatus = status;
        switchStatusLayout();
    }

    public void setStatus(@Status int status, OnClickListener onClickListener){
        this.mStatus = status;
        switchStatusLayout();
        mTvFailMsg.setOnClickListener(onClickListener);
    }

    private void switchStatusLayout() {
        switch (mStatus){
            case STATUS_LOADING:
                showLoading();
                break;
            case STATUS_LOAD_FAIL:
                showLoadFail();
                break;
            case STATUS_HIDE:
                hint();
                break;
        }
    }

    private void showLoadFail() {
        // 判断网络是否可用
        boolean isAvailable = networkIsAvailable(getContext());
        if (isAvailable) {
            mTvFailMsg.setText("加载失败, 点击重试");
            mTvFailMsg.setCompoundDrawablesWithIntrinsicBounds(null
                    , ContextCompat.getDrawable(mContext, R.mipmap.ic_load_fail), null, null);
        }else{
            mTvFailMsg.setText("网络异常, 点击重试");
            mTvFailMsg.setCompoundDrawablesWithIntrinsicBounds(null
                    , ContextCompat.getDrawable(mContext, R.mipmap.ic_not_network), null, null);
        }
        show();
        mLlLoading.setVisibility(GONE);
        mFlFailContainer.setVisibility(VISIBLE);
    }

    private void showLoading() {
        show();
        mFlFailContainer.setVisibility(GONE);
        mLlLoading.setVisibility(VISIBLE);
    }

    private void show(){
        setVisibility(VISIBLE);
    }

    private void hint(){
        setVisibility(GONE);
    }

    /**
     * 检测网络是否可用
     */
    public boolean networkIsAvailable(Context context) {
        try {
            ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            if (cm != null) {
                NetworkInfo info = cm.getActiveNetworkInfo();
                if (info != null && info.isConnected()) {
                    if (info.getState() == NetworkInfo.State.CONNECTED) {
                        return true;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
}

布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:id="@+id/rl_status"
              android:background="@android:color/white"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <FrameLayout
        android:id="@+id/fl_fail_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/tv_fail_msg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="14sp"
            android:textColor="#333333"
            android:layout_gravity="center"
            android:text="网络异常, 点击重试"
            android:drawableTop="@mipmap/ic_not_network"
            android:drawablePadding="10dp"/>

    </FrameLayout>
    
    <LinearLayout
        android:id="@+id/ll_loading"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical"
        android:visibility="gone">

        <ProgressBar
            android:layout_width="30dp"
            android:layout_height="30dp"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="12sp"
            android:textColor="#333333"
            android:text="正在加载中..."
            android:layout_marginTop="15dp"/>

    </LinearLayout>

</RelativeLayout>

2.封装多状态布局的工具类

package com.mir.datepicker;

import android.app.Activity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;

/**
 * @data 2018-08-01
 * @desc
 */

public class StatusUtils {

    private Activity mActivity;
    private ViewGroup mViewGroup;
    private StatusLayout mStatusLayout;
    private RelativeLayout mRlStatus;

    static StatusUtils mStatusUtils = null;

    public StatusUtils(Activity activity){
        this.mActivity = activity;
    }

    public StatusUtils(ViewGroup viewGroup) {
        mViewGroup = viewGroup;
    }

    public static StatusUtils create(Activity activity){
        mStatusUtils = new StatusUtils(activity);
        return mStatusUtils;
    }

    public static StatusUtils create(ViewGroup viewGroup){
        mStatusUtils = new StatusUtils(viewGroup);
        return mStatusUtils;
    }

    void showLoading(){
        if (mActivity != null) {
            mRlStatus = mActivity.findViewById(R.id.rl_status);
            if (mRlStatus == null) {
                mStatusLayout = new StatusLayout(mActivity);
                mActivity.addContentView(mStatusLayout, new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
            }else{
                mStatusLayout = (StatusLayout) mRlStatus.getParent();
            }
            mStatusLayout.setStatus(StatusLayout.STATUS_LOADING);
        } else if (mViewGroup != null) {
            mRlStatus = mViewGroup.findViewById(R.id.rl_status);
            if (mRlStatus == null) {
                mStatusLayout = new StatusLayout(mViewGroup.getContext());
                mViewGroup.addView(mStatusLayout, new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
            }else{
                mStatusLayout = (StatusLayout) mRlStatus.getParent();
            }
            mStatusLayout.setStatus(StatusLayout.STATUS_LOADING);
        }
    }

    void hint(){
        if (mActivity != null) {
            mRlStatus = mActivity.findViewById(R.id.rl_status);
            if (mRlStatus == null) {
                mStatusLayout = new StatusLayout(mActivity);
                mActivity.addContentView(mStatusLayout, new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
            }else{
                mStatusLayout = (StatusLayout) mRlStatus.getParent();
            }
            mStatusLayout.setStatus(StatusLayout.STATUS_HIDE);
        } else if (mViewGroup != null) {
            mRlStatus = mViewGroup.findViewById(R.id.rl_status);
            if (mRlStatus == null) {
                mStatusLayout = new StatusLayout(mViewGroup.getContext());
                mViewGroup.addView(mStatusLayout, new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
            }else{
                mStatusLayout = (StatusLayout) mRlStatus.getParent();
            }
            mStatusLayout.setStatus(StatusLayout.STATUS_HIDE);
        }
    }

    void fail(View.OnClickListener onClickListener){
        if (mActivity != null) {
            mRlStatus = mActivity.findViewById(R.id.rl_status);
            if (mRlStatus == null) {
                mStatusLayout = new StatusLayout(mActivity);
                mActivity.addContentView(mStatusLayout, new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
            }else{
                mStatusLayout = (StatusLayout) mRlStatus.getParent();
            }
            mStatusLayout.setStatus(StatusLayout.STATUS_LOAD_FAIL, onClickListener);
        } else if (mViewGroup != null) {
            mRlStatus = mViewGroup.findViewById(R.id.rl_status);
            if (mRlStatus == null) {
                mStatusLayout = new StatusLayout(mViewGroup.getContext());
                mViewGroup.addView(mStatusLayout, new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
            }else{
                mStatusLayout = (StatusLayout) mRlStatus.getParent();
            }
            mStatusLayout.setStatus(StatusLayout.STATUS_LOAD_FAIL, onClickListener);
        }
    }

}

3.使用

 findViewById(R.id.btn5).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //mFrameLayout 要展示多状态的布局返回
                StatusUtils.create(mFrameLayout).showLoading(); //设置加载中状态
            }
        });

        findViewById(R.id.btn6).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                StatusUtils.create(mFrameLayout).fail(new View.OnClickListener() { //设置加载失败状态
                    @Override
                    public void onClick(View view) {
                        StatusUtils.create(mFrameLayout).showLoading();
                        new Handler().postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                StatusUtils.create(mFrameLayout).hint();
                            }
                        }, 2000);
                    }
                });
            }
        });

        findViewById(R.id.btn7).setOnClickListener(new View.OnClickListener() { //隐藏多状态布局, 显示主布局
            @Override
            public void onClick(View view) {
                StatusUtils.create(mFrameLayout).hint();
            }
        });

总结 : 使用起来很方便, 一句话搞定多状态布局,无需封装到BaseActivity和BaseFragment里,直接调用工具类既可。工具类传入Activity,当前Activity整体页面会被多状态布局遮盖,传入ViewGroup,多状态布局只会覆盖,ViewGroup的范围 。

github : https://github.com/a1498506790/DatePicker

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值