@xujun94
2016-07-18T00:15:43.000000Z
字数 7358
阅读 1193
最近在做项目的时候,刚开始没有考虑空界面,错误界面的处理,一开始是想为每个界面在布局文件中都添加一个错误界面,空界面,但仔细一想,这样的工作量太大了,而且也不方便处理,于是我想能不能做出一个自定义控件出来,想了挺久,终于做出来了,现在将其分享出来,有什么不足的请各位指点。
本文固定链接:https://www.zybuluo.com/xujun94/note/421494
源码下载地址:
转载请注明原博客地址:
package com.szl.loadinngpagedemo.view;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import com.szl.loadinngpagedemo.R;
/***
* 创建了自定义帧布局 把baseFragment 一部分代码 抽取到这个类中
*
* @author itcast
*/
public abstract class LoadingPage extends FrameLayout {
public static final int STATE_UNKOWN = 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_SUCCESS = 4;
public int state = STATE_UNKOWN;
private Context mContext;
private View loadingView;// 加载中的界面
private View errorView;// 错误界面
private View emptyView;// 空界面
private View successView;// 加载成功的界面
public LoadingPage(Context context) {
this(context,null,0);
}
public LoadingPage(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public LoadingPage(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
init();
}
private void init() {
loadingView = createLoadingView(); // 创建了加载中的界面
if (loadingView != null) {
this.addView(loadingView, new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
}
errorView = createErrorView(); // 加载错误界面
if (errorView != null) {
this.addView(errorView, new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
}
emptyView = createEmptyView(); // 加载空的界面
if (emptyView != null) {
this.addView(emptyView, new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
}
/**
* 注意这里依赖是就初始化成功的界面,也可以在状态成功的时候才初始化成功的界面
*/
successView = createSuccessView();
if(successView!=null){
this.addView(successView, new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
}
showPage();// 根据不同的状态显示不同的界面
}
// 根据不同的状态显示不同的界面
private void showPage() {
if (loadingView != null) {
loadingView.setVisibility(state == STATE_UNKOWN
|| state == STATE_LOADING ? View.VISIBLE : View.INVISIBLE);
}
if (errorView != null) {
errorView.setVisibility(state == STATE_ERROR ? View.VISIBLE
: View.INVISIBLE);
}
if (emptyView != null) {
emptyView.setVisibility(state == STATE_EMPTY ? View.VISIBLE
: View.INVISIBLE);
}
if (state == STATE_SUCCESS) {
if (successView == null) {
successView = createSuccessView();
this.addView(successView, new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
}
successView.setVisibility(View.VISIBLE);
} else {
if (successView != null) {
successView.setVisibility(View.INVISIBLE);
}
}
}
/* 创建了空的界面 */
private View createEmptyView() {
View view = View.inflate(mContext, R.layout.loadpage_empty,
null);
return view;
}
/* 创建了错误界面 */
private View createErrorView() {
View view = View.inflate(mContext, R.layout.loadpage_error,
null);
Button page_bt = (Button) view.findViewById(R.id.page_bt);
page_bt.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
}
});
return view;
}
/* 创建加载中的界面 */
private View createLoadingView() {
View view = View.inflate(mContext,
R.layout.loadpage_loading, null);
return view;
}
/**
* 枚举类,对应相应的状态码,用来表示各种状态
*/
public enum LoadResult {
loading(1),error(2), empty(3), success(4);
int value;
LoadResult(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
/**
* 注意请求成功后必须调用show方法,会根据这个压面显示相应的数据
* @param loadResult
*/
public void show(LoadResult loadResult) {
state = loadResult.getValue();
showPage();
}
/***
* 创建成功的界面
*
* @return
*/
public abstract View createSuccessView();
}
private View loadingView;// 加载中的界面
private View errorView;// 错误界面
private View emptyView;// 空界面
private View successView;// 加载成功的界面
errorView = createErrorView(); // 加载错误界面
emptyView = createEmptyView(); // 加载空的界面
successView = createSuccessView();//加载成功的界面
注意在init()方法里面我们可以知道 createSuccessView()是一个抽象方法,因为每个Activity或Fragment的成功界面一般是变异羊的,我们交给子类自己去实现
public int state = STATE_UNKOWN;
loadingView.setVisibility(state == STATE_UNKOWN
|| state == STATE_LOADING ? View.VISIBLE : View.INVISIBLE);
errorView.setVisibility(state == STATE_ERROR ? View.VISIBLE
: View.INVISIBLE);
-------
效果图如下:
当然我们只需调用void show(LoadResult loadResult)这个方法即可根据相应的状态显示相应的界面
public abstract class BaseFragment extends Fragment {
protected LoadingPage mLoadingPage;
Context mContext;
Activity mActivity;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mContext=getActivity();
mActivity=getActivity();
if (mLoadingPage == null) { // 之前的frameLayout 已经记录了一个爹了 爹是之前的ViewPager
mLoadingPage = new LoadingPage(this.mContext) {
@Override
public View createSuccessView() {
return BaseFragment.this.createSuccessView();
}
};
} else {
ViewUtils.removeParent(mLoadingPage);// 移除frameLayout之前的爹
}
return mLoadingPage; // 拿到当前viewPager 添加这个framelayout
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initData();
}
protected void initData() {
}
/***
* 创建成功的界面
*
* @return
*/
public abstract View createSuccessView();
public void show(LoadResult loadResult) {
if (mLoadingPage != null) {
mLoadingPage.show(loadResult);
}
}
/**
* 校验数据
*/
public LoadResult checkData(List datas) {
if (datas == null) {
return LoadResult.error;// 请求服务器失败
} else {
if (datas.size() == 0) {
return LoadingPage.LoadResult.empty;
} else {
return LoadingPage.LoadResult.success;
}
}
}
}
BaseFragment的代码很简单,就是将我们的LoadPager这个自定义View设置为根布局,然后创建成功的界面由子类自己去实现
public class ErrorFragment extends BaseFragment {
@Override
public View createSuccessView() {
return View.inflate(mContext,R.layout.fragemnt_test,null);
}
@Override
protected void initData() {
mLoadingPage.postDelayed(new Runnable() {
@Override
public void run() {
show(LoadingPage.LoadResult.error);
}
},2500);
}
}
我们可以看到我们所做的就是创建自己的成功界面,如果想显示别的界面,就调用void show(LoadResult loadResult)这个方法,这个我们延时之后调用 show(LoadingPage.LoadResult.error);来显示错误界面
看ErrorFragment的代码以后,我们可以轻易地想到我们的EmptyFragment是怎样操作的,没错就是调用show(LoadingPage.LoadResult.empty);这个方法而已
public class EmptyFragment extends BaseFragment {
@Override
public View createSuccessView() {
return View.inflate(mContext,R.layout.fragemnt_test,null);
}
@Override
protected void initData() {
mLoadingPage.postDelayed(new Runnable() {
@Override
public void run() {
show(LoadingPage.LoadResult.empty);
}
},2500);
}
}
同理SuccessFragemnt的代码你也能轻易的想象得到,这里就不贴出来了
/**
* 博客地址:http://blog.csdn.net/gdutxiaoxu
* @author xujun
* @time 2016-6-29 14:52.
*/
public abstract class BaseActivity extends AppCompatActivity {
protected Context mContext;
protected ProgressDialog dialog;
protected LoadingPage mLoadingPage;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
initWindows();
// base setup
mContext = this;
if (mLoadingPage == null) {
mLoadingPage = new LoadingPage(this) {
@Override
public View createSuccessView() {
return BaseActivity.this.createSuccessView();
}
};
} else {
ViewUtils.removeParent(mLoadingPage);
}
setContentView(mLoadingPage);
dialog = new ProgressDialog(this);
initListener();
initData();
}
public void show(LoadingPage.LoadResult loadResult){
if(mLoadingPage!=null){
mLoadingPage.show(loadResult);
}
}
/**
* 创造成功的页面
*
* @return
*/
protected abstract View createSuccessView();
----
思路其实很简单,一开始给LoadPager初始化各种布局,包括错误界面,加载中的界面,空界面,其中成功的界面交友子类自己去实现,如果我们想显示别的界面的话,我们只需要调用void show(LoadResult loadResult)这个方法而已