package com.cheikh.lazywaimai.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.support.annotation.DrawableRes;
import android.support.annotation.IntDef;
import android.support.annotation.LayoutRes;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import com.cheikh.lazywaimai.R;
/**
* 一个提供多种状态切换显示的 layout 组件
* author:cheikh.wang on 16/7/12 11:34
* email:wanghonghi@126.com
* 修改自:https://github.com/Kennyc1012/MultiStateView
*/
public class MultiStateView extends FrameLayout {
public static final int STATE_CONTENT = 0;
public static final int STATE_LOADING = 1;
public static final int STATE_ERROR = 2;
public static final int STATE_EMPTY = 3;
public static final int STATE_UNAUTH = 4;
public static final int DEFAULT_STATE = STATE_LOADING;
@Retention(RetentionPolicy.SOURCE)
@IntDef({
STATE_CONTENT,
STATE_LOADING,
STATE_ERROR,
STATE_EMPTY,
STATE_UNAUTH
})
public @interface State {
}
private View mContentView;
private View mLoadingView;
private View mErrorView;
private View mEmptyView;
private View mUnauthView;
private LayoutInflater mInflater;
@State
private int mState;
public MultiStateView(Context context) {
this(context, null);
}
public MultiStateView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public MultiStateView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs);
}
private void init(AttributeSet attrs) {
mInflater = LayoutInflater.from(getContext());
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MultiStateView);
// 加载中视图布局
int loadingViewResId = a.getResourceId(R.styleable.MultiStateView_msv_loadingView, -1);
if (loadingViewResId > -1) {
mLoadingView = mInflater.inflate(loadingViewResId, this, false);
addView(mLoadingView);
}
// 错误视图布局
int errorViewResId = a.getResourceId(R.styleable.MultiStateView_msv_errorView, -1);
if (errorViewResId > -1) {
mErrorView = mInflater.inflate(errorViewResId, this, false);
addView(mErrorView);
}
// 空视图布局
int emptyViewResId = a.getResourceId(R.styleable.MultiStateView_msv_emptyView, -1);
if (emptyViewResId > -1) {
mEmptyView = mInflater.inflate(emptyViewResId, this, false);
addView(mEmptyView);
}
// 未登录视图布局
int unauthViewResId = a.getResourceId(R.styleable.MultiStateView_msv_unauthView, -1);
if (unauthViewResId > -1) {
mUnauthView = mInflater.inflate(unauthViewResId, this, false);
addView(mUnauthView);
}
// 默认状态.由于mViewState变量使用了注解限制,所以不能直接赋值
int viewState = a.getInt(R.styleable.MultiStateView_msv_viewState, DEFAULT_STATE);
switch (viewState) {
case STATE_CONTENT:
mState = STATE_CONTENT;
break;
case STATE_LOADING:
mState = STATE_LOADING;
break;
case STATE_ERROR:
mState = STATE_ERROR;
break;
case STATE_EMPTY:
mState = STATE_EMPTY;
break;
default:
// nothing to do
break;
}
a.recycle();
initDefaultViews();
}
/**
* 初始化各个状态对应的默认视图
*/
private void initDefaultViews() {
if (mLoadingView == null) {
mLoadingView = mInflater.inflate(R.layout.layout_loading_hint, this, false);
addView(mLoadingView);
}
if (mErrorView == null) {
mErrorView = mInflater.inflate(R.layout.layout_error_hint, this, false);
addView(mErrorView);
}
if (mEmptyView == null) {
mEmptyView = mInflater.inflate(R.layout.layout_empty_hint, this, false);
addView(mEmptyView);
}
if (mUnauthView == null) {
mUnauthView = mInflater.inflate(R.layout.layout_unauth_hint, this, false);
addView(mUnauthView);
}
}
@Override
public void onViewAdded(View child) {
super.onViewAdded(child);
if (isValidContentView(child)) {
mContentView = child;
}
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (mContentView == null) throw new IllegalArgumentException("Content view is not defined");
setView();
}
/**
* 检测是否是Content View
* @param view
* @return
*/
private boolean isValidContentView(View view) {
if (mContentView != null && mContentView != view) {
return false;
}
return view != mLoadingView && view != mErrorView
&& view != mEmptyView && view != mUnauthView;
}
@Nullable
public View getView(@State int state) {
switch (state) {
case STATE_CONTENT:
return mContentView;
case STATE_LOADING:
return mLoadingView;
case STATE_ERROR:
return mErrorView;
case STATE_EMPTY:
return mEmptyView;
default:
return null;
}
}
/**
* 切换显示的状态视图的逻辑
*/
private void setView() {
switch (mState) {
case STATE_CONTENT:
mContentView.setVisibility(View.VISIBLE);
mLoadingView.setVisibility(View.GONE);
mErrorView.setVisibility(View.GONE);
mEmptyView.setVisibility(View.GONE);
mUnauthView.setVisibility(View.GONE);
break;
case STATE_LOADING:
mContentView.setVisibility(View.GONE);
mLoadingView.setVisibility(View.VISIBLE);
mErrorView.setVisibility(View.GONE);
mEmptyView.setVisibility(View.GONE);
mUnauthView.setVisibility(View.GONE);
break;
case STATE_ERROR:
mContentView.setVisibility(View.GONE);
mLoadingView.setVisibility(View.GONE);
mErrorView.setVisibility(View.VISIBLE);
mEmptyView.setVisibility(View.GONE);
mUnauthView.setVisibility(View.GONE);
break;
case STATE_EMPTY:
mContentView.setVisibility(View.GONE);
mLoadingView.setVisibility(View.GONE);
mErrorView.setVisibility(View.GONE);
mEmptyView.setVisibility(View.VISIBLE);
mUnauthView.setVisibility(View.GONE);
break;
case STATE_UNAUTH:
mContentView.setVisibility(View.GONE);
mLoadingView.setVisibility(View.GONE);
mErrorView.setVisibility(View.GONE);
mEmptyView.setVisibility(View.GONE);
mUnauthView.setVisibility(View.VISIBLE);
break;
default:
// nothing to do
break;
}
}
///////////////////////////////////////////////
//// 以下是供外部操作的公有方法 ////
///////////////////////////////////////////////
/**
* 设置指定状态的视图
* @param view
* @param state
* @param switchToState
*/
public MultiStateView setViewForState(View view, @State int state, boolean switchToState) {
switch (state) {
case STATE_CONTENT:
if (mContentView != null) {
removeView(mContentView);
}
mContentView = view;
addView(mContentView);
break;
case STATE_LOADING:
if (mLoadingView != null) {
removeView(mLoadingView);
}
mLoadingView = view;
addView(mLoadingView);
break;
case STATE_ERROR:
if (mErrorView != null) {
removeView(mErrorView);
}
mErrorView = view;
addView(mErrorView);
break;
case STATE_EMPTY:
if (mEmptyView != null) {
removeView(mEmptyView);
}
mEmptyView = view;
addView(mEmptyView);
break;
case STATE_UNAUTH:
if (mUnauthView != null) {
removeView(mUnauthView);
}
mUnauthView = view;
addView(mUnauthView);
break;
default:
// nothing to do
break;
}
setView();
// 是否立即切换状态
if (switchToState) {
setState(state);
}
return this;
}
/**
* 设置指定状态的视图
* @param view
* @param state
*/
public MultiStateView setViewForState(View view, @State int state) {
return setViewForState(view, state, false);
}
/**
* 设置指定状态的视图
* @param layoutRes
* @param state
* @param switchToState
*/
public MultiStateView setViewForState(@LayoutRes int layoutRes, @State int state, boolean switchToState) {
View view = mInflater.inflate(layoutRes, this, false);
return setViewForState(view, state, switchToState);
}
/**
* 设置指定状态的视图
* @param layoutRes
* @param state
*/
public MultiStateView setViewForState(@LayoutRes int layoutRes, @State int state) {
return setViewForState(layoutRes, state, false);
}
/**
* 获取当前的状态
* @return
*/
@State
public int getState() {
return mState;
}
/**
* 切换显示的状态
* @param state
* @return
*/
public MultiStateView setState(@State int state) {
if (state != mState) {
mState = state;
setView();
}
return this;
}
/**
* 设置当前状态视图的图标
* @param iconResId
* @return
*/
public MultiStateView setIcon(@DrawableRes int iconResId) {
View view = getView(mState);
if (view != null) {
ImageView icon = (ImageView) view.findViewById(R.id.icon);
if (icon != null) {
icon.setImageResource(iconResId);
} else {
throw new IllegalArgumentException("view must have an id of named icon");
}
}
return this;
}
/**
* 设置当前状态视图的标题
* @param titleResId
* @return
*/
public MultiStateView setTitle(@StringRes int titleResId) {
return setTitle(getContext().getString(titleResId));
}
/**
* 设置当前状态视图的标题
* @param title
* @return
*/
public MultiStateView setTitle(String title) {
View view = getView(mState);
if (view != null) {
TextView titleTxt = (TextView) view.findViewById(R.id.title);
if (titleTxt != null) {
titleTxt.setVisibility(View.VISIBLE);
titleTxt.setText(title);
} else {
throw new IllegalArgumentException(view.getClass().getSimpleName() + " must have an id of named title");
}
}
return this;
}
/**
* 设置当前状态视图的子标题
* @param subtitleResId
* @return
*/
public MultiStateView setSubtitle(@StringRes int subtitleResId) {
return setSubtitle(getContext().getString(subtitleResId));
}
/**
* 设置当前状态视图的子标题
* @param subtitle
* @return
*/
public MultiStateView setSubtitle(String subtitle) {
View view = getView(mState);
if (view != null) {
TextView titleTxt = (TextView) view.findViewById(R.id.subtitle);
if (titleTxt != null) {
titleTxt.setVisibility(View.VISIBLE);
titleTxt.setText(subtitle);
} else {
throw new IllegalArgumentException(view.getClass().getSimpleName() + " must have an id of named subtitle");
}
}
return this;
}
/**
* 设置当前状态视图的按钮点击事件
* @param listener
* @return
*/
public MultiStateView setButton(OnClickListener listener) {
return setButton(null, listener);
}
/**
* 设置当前状态视图的按钮文字和点击事件
* @param textResId
* @param listener
* @return
*/
public MultiStateView setButton(@StringRes int textResId, OnClickListener listener) {
return setButton(getContext().getString(textResId), listener);
}
/**
* 设置当前状态视图的按钮文字和点击事件
* @param text
* @param listener
* @return
*/
public MultiStateView setButton(String text, OnClickListener listener) {
View view = getView(mState);
if (view != null) {
View button = view.findViewById(R.id.button);
// 这个button只能是TextView或者Button控件
if (button != null && (button instanceof Button || button instanceof TextView)) {
button.setVisibility(VISIBLE);
if (text != null && !text.equals("")) {
if (button instanceof Button) {
((Button) button).setText(text);
} else {
((TextView) button).setText(text);
}
}
if (listener != null) {
button.setOnClickListener(listener);
}
} else {
throw new IllegalArgumentException(view.getClass().getSimpleName() + " view must have an id of named button");
}
}
return this;
}
}