针对ListView有setEmpty方法来设置加载失败时的默认显示页面,但扩展性太差。有没有通用性更强,适用为任意布局添加加载中等状态布局的方法呢?
答案是肯定的,接下来我们就去实现这样一个帮助类。申明LoadingViewHelper类,由于加载成功显示的布局为目标显示界面,所以采用构造方法注入。对于加载中以及加载失败显示的布局,申明为抽象方法,由子类决定是否实现,这样增加了扩展性。
updateLoadingView方法负责根据mLoadingStatus切换显示对应的布局,其中针对View的获取进行了优化,以免重复实例化loadingView和failedView。
changeLoadingStatus为外界提供访问接口,在业务层可控制显示加载状态对应的View。
/**
* Created by Administrator on 2016/6/22.
* 加载View时各种情况下的View显示
* 未考虑提示View的宽高超出SucceedView的情况,需要自定义控制非SucceedView的宽高在SuceedView内部
*/
public abstract class LoadingViewHelper {
public static final UtilsLog lg = UtilsLogFactory.getLogger(LoadingViewHelper.class);
private View loadingView;
private View succeedView;//绑定的布局,用于加载成功时显示
private View failedView;
private ViewGroup parentViewGroup;//父布局
private LoadingStatus mLoadingStatus;//默认为加载中
/**
* 不支持SucceedView的父布局为
*
* @param succeedView
*/
public LoadingViewHelper(View succeedView) {
this.succeedView = succeedView;
this.parentViewGroup = (ViewGroup) succeedView.getParent();
if (parentViewGroup == null) {
//此时succeedView为getDecorView,需要调整
lg.e("ParentViewGroup is null:当前View为getWindow().getDecorView()");
this.parentViewGroup = (ViewGroup) (succeedView.findViewById(android.R.id.content));
this.succeedView = this.parentViewGroup.getChildAt(0);
}
this.mLoadingStatus = LoadingStatus.Loading;
updateLoadingView();
}
/**
* 根据LoadingStatus切换View显示
*/
private void updateLoadingView() {
switch (mLoadingStatus) {
case Loading:
lg.e("updateLoadingView:Loading");
if (loadingView == null) {
loadingView = getLoadingView();
/*添加至布局中*/
if (loadingView != null) {
ViewGroup.LayoutParams layoutParams = succeedView.getLayoutParams();
parentViewGroup.addView(loadingView, layoutParams);
}
}
settingViewVisibilityIfViewNotNull(loadingView, View.VISIBLE)
.settingViewVisibilityIfViewNotNull(succeedView, View.GONE)
.settingViewVisibilityIfViewNotNull(failedView, View.GONE);
break;
case Success:
lg.e("updateLoadingView:Success");
settingViewVisibilityIfViewNotNull(loadingView, View.GONE)
.settingViewVisibilityIfViewNotNull(succeedView, View.VISIBLE)
.settingViewVisibilityIfViewNotNull(failedView, View.GONE);
break;
case Faild:
lg.e("updateLoadingView:Faild");
if (failedView == null) {
failedView = getFailedView(succeedView);
if (failedView != null) {
ViewGroup.LayoutParams layoutParams = succeedView.getLayoutParams();
parentViewGroup.addView(failedView, layoutParams);
}
}
settingViewVisibilityIfViewNotNull(loadingView, View.GONE)
.settingViewVisibilityIfViewNotNull(succeedView, View.GONE)
.settingViewVisibilityIfViewNotNull(failedView, View.VISIBLE);
break;
}
}
/**
* 若View非空,则切换显示方式
*
* @param view
* @param visibility
* @return
*/
private LoadingViewHelper settingViewVisibilityIfViewNotNull(View view, int visibility) {
if (view != null) {
view.setVisibility(visibility);
}
return this;
}
/**
* 切换更新状态
*
* @param loadingStatus
*/
public void changeLoadingStatus(LoadingStatus loadingStatus) {
if (loadingStatus != null) {
this.mLoadingStatus = loadingStatus;
updateLoadingView();
}
}
public enum LoadingStatus {
Loading, Success, Faild;
}
/**
* 获取加载状态中显示的布局
*
* @return
*/
public abstract View getLoadingView();
/**
* 获取加载失败显示的布局
*
* @param succeedView
* @return
*/
public abstract View getFailedView(View succeedView);
}
具体在业务层的使用方式如下,postDelayed模拟请求数据的耗时操作,这里的getFailedView方法中自定义请求重试事件。
final LoadingViewHelper loadingViewHelper = new LoadingViewHelper(btnActCahngeSkinShowStyle) {
@Override
public View getLoadingView() {
ImageView imageView = new ImageView(getCurActivity());
imageView.setImageResource(R.mipmap.ic_famer_help_seize);
imageView.setBackgroundColor(Color.RED);
return imageView;
}
@Override
public View getFailedView(View succeedView) {
Button btn = new Button(getCurActivity());
btn.setText("点击重试");
btn.setBackgroundColor(Color.YELLOW);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
changeLoadingStatus(LoadingStatus.Loading);
AppHelper.getInstance().getLooperHandler().postDelayed(new Runnable() {
@Override
public void run() {
changeLoadingStatus(LoadingStatus.Success);
}
}, 10000);
}
});
return btn;
}
};
AppHelper.getInstance().getLooperHandler().postDelayed(new Runnable() {
@Override
public void run() {
loadingViewHelper.changeLoadingStatus(LoadingViewHelper.LoadingStatus.Faild);
}
}, 10000);
ok,这下所有的View都能添加加载状态的View显示效果了。