无侵入性实现, 不需要每一个布局都引入多状态布局
先上图
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的范围 。