先上图
如图所示,页面主要有三个模块.
空页面:表示联网成功,但是服务器没有数据可取的页面提示
错误页面:表示网络等错误的页面提示.
内容页面:就是我们正常流程显示的页面.
为了结构精简,你只需要引用一个类StateTool就行!!!!精简到没朋友..
开始讲解StateTool
package com.yao.statetooldemo;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
/**
* Created by Yao on 2016/9/28.
*/
public class StateTool {
/**
* 一大堆静态变量,根据项目需要可以随意修改.比如项目全部用同一张错误页面的图片.
* 在一个项目中如果用好几张不同的错误页面图片,可以考虑改成成员变量.
*/
//内容字体的大小,单位SP
private static int CONTENT_TEXT_SIZE = 20;
//提示字体的大小,单位SP
private static int TIP_TEXT_SIZE = 12;
//空页面图片,默认用的安卓sdk里面的图片,严重建议替换成一个256px左右的图片 默认使用android.R.drawable.ic_menu_close_clear_cancel
private static int emptyImageResId = R.mipmap.empty;
//错误页面图片,默认用的安卓sdk里面的图片,严重建议替换成一个256px左右的图片 默认使用android.R.drawable.ic_menu_search
private static int errorImageResId = R.mipmap.error;
//空页面文字
private static String emptyText = "空页面";
//错误页面文字
private static String errorText = "错误页面";
//加载页面文字
private static String loadingText = "加载中...";
//重载动作的文字提示
private static String reloadText = "点击重载";
//图片的宽和高 可以用ViewGroup.LayoutParams.WRAP_CONTENT
private static int imageSidesLength = 128;
//等待,错误,空页面提示的向上偏移
private static int offset = 0;
//使用淡入淡出动画
private static boolean useAlphaAnimator = false;
private ViewGroup root;
private Context ctx;
private View contentView;
private RelativeLayout emptyView;
private RelativeLayout errorView;
private RelativeLayout progressView;
private View currentView;
private LinearLayout.LayoutParams paramsChildrenWrapContent;
private LinearLayout.LayoutParams paramsChildrenImage;
private LinearLayout.LayoutParams paramsChildrenMarginBottom50;
/**
* 一个孩子,调用此方法
* @param root
*/
public StateTool(ViewGroup root) {
this.root = root;
if (root.getChildCount() > 1) {
throw new RuntimeException("root view's children more than 1");
}
contentView = root.getChildAt(0);
init();
}
/**
* 如果有多个孩子,调用此方法
* @param root
* @param index 传孩子的位置
*/
public StateTool(ViewGroup root, int index) {
this.root = root;
if (root.getChildCount() < index + 1) {
throw new RuntimeException("Invalid index " + index +", size is " + root.getChildCount());
}
contentView = root.getChildAt(index);
init();
}
private void init() {
ctx = root.getContext();
currentView = contentView;
paramsChildrenWrapContent = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
paramsChildrenImage = new LinearLayout.LayoutParams(imageSidesLength, imageSidesLength);
paramsChildrenMarginBottom50 = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
paramsChildrenMarginBottom50.setMargins(0, 0, 0, offset);//不margin不居中
initEmptyView();
initErrorView();
initProgressView();
}
public void setEmptyAndErrorImageResId(int emptyImageResId, int errorImageResId) {
this.emptyImageResId = emptyImageResId;
this.errorImageResId = errorImageResId;
}
public void setEmptyAndErrorTextResId(String emptyText, String errorText, String reloadText, String loadingText) {
this.emptyText = emptyText;
this.errorText = errorText;
this.reloadText = reloadText;
this.loadingText = loadingText;
}
public void showEmptyView(){
if (useAlphaAnimator) {
alphaHide(currentView);
alphaShow(emptyView);
} else {
currentView.setVisibility(View.GONE);
emptyView.setVisibility(View.VISIBLE);
}
currentView = emptyView;
}
public void showErrorView(){
currentView.setVisibility(View.GONE);
errorView.setVisibility(View.VISIBLE);
currentView = errorView;
}
public void showProgressView(){
currentView.setVisibility(View.GONE);
progressView.setVisibility(View.VISIBLE);
currentView = progressView;
}
public void showContentView(){
currentView.setVisibility(View.GONE);
contentView.setVisibility(View.VISIBLE);
currentView = contentView;
}
public void setOnClickListener(View.OnClickListener onClickListener) {
emptyView.setOnClickListener(onClickListener);
errorView.setOnClickListener(onClickListener);
}
private void alphaShow(final View v){
ObjectAnimator oa = ObjectAnimator.ofFloat(v, "alpha", 0, 1);
oa.setDuration(500);
oa.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animator) {
v.setVisibility(View.VISIBLE);
}
});
oa.start();
}
private void alphaHide(final View v){
ObjectAnimator oa = ObjectAnimator.ofFloat(v, "alpha", 1, 0);
oa.setDuration(500);
oa.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animator) {
v.setVisibility(View.GONE);
}
});
oa.start();
}
private void initEmptyView() {
emptyView = new RelativeLayout(ctx);
LinearLayout linearLayout = new LinearLayout(ctx);
linearLayout.setOrientation(LinearLayout.VERTICAL);
ImageView iv = new ImageView(ctx);
iv.setImageResource(emptyImageResId);
linearLayout.addView(iv, paramsChildrenImage);
TextView tvContent = new TextView(ctx);
tvContent.setTextSize(TypedValue.COMPLEX_UNIT_SP, CONTENT_TEXT_SIZE);
tvContent.setText(emptyText);
linearLayout.addView(tvContent, paramsChildrenWrapContent);
TextView tvTip = new TextView(ctx);
tvTip.setTextSize(TypedValue.COMPLEX_UNIT_SP, TIP_TEXT_SIZE);
tvTip.setText(reloadText);
linearLayout.addView(tvTip, paramsChildrenMarginBottom50);
RelativeLayout.LayoutParams paramsLinearLayout = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
paramsLinearLayout.addRule(RelativeLayout.CENTER_IN_PARENT);//这个是RelativeLayout的layout_centerInParent属性
linearLayout.setGravity(Gravity.CENTER);//这个是LinearLayout的gravity属性
emptyView.addView(linearLayout, paramsLinearLayout);
root.addView(emptyView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
emptyView.setVisibility(View.GONE);
}
private void initErrorView() {
errorView = new RelativeLayout(ctx);
LinearLayout linearLayout = new LinearLayout(ctx);
linearLayout.setOrientation(LinearLayout.VERTICAL);
ImageView iv = new ImageView(ctx);
iv.setImageResource(errorImageResId);
linearLayout.addView(iv, paramsChildrenImage);
TextView tvContent = new TextView(ctx);
tvContent.setTextSize(TypedValue.COMPLEX_UNIT_SP, CONTENT_TEXT_SIZE);
tvContent.setText(errorText);
linearLayout.addView(tvContent, paramsChildrenWrapContent);
TextView tvTip = new TextView(ctx);
tvTip.setTextSize(TypedValue.COMPLEX_UNIT_SP, TIP_TEXT_SIZE);
tvTip.setText(reloadText);
linearLayout.addView(tvTip, paramsChildrenMarginBottom50);
RelativeLayout.LayoutParams paramsLinearLayout = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
paramsLinearLayout.addRule(RelativeLayout.CENTER_IN_PARENT);//这个是RelativeLayout的layout_centerInParent属性
linearLayout.setGravity(Gravity.CENTER);//这个是LinearLayout的gravity属性
errorView.addView(linearLayout, paramsLinearLayout);
root.addView(errorView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
errorView.setVisibility(View.GONE);
}
private void initProgressView() {
progressView = new RelativeLayout(ctx);
LinearLayout linearLayout = new LinearLayout(ctx);
linearLayout.setOrientation(LinearLayout.VERTICAL);
ProgressBar pb = new ProgressBar(ctx);
linearLayout.addView(pb, paramsChildrenWrapContent);
TextView tvContent = new TextView(ctx);
tvContent.setTextSize(TypedValue.COMPLEX_UNIT_SP, CONTENT_TEXT_SIZE);
tvContent.setText(loadingText);
linearLayout.addView(tvContent, paramsChildrenMarginBottom50);
RelativeLayout.LayoutParams paramsLinearLayout = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
paramsLinearLayout.addRule(RelativeLayout.CENTER_IN_PARENT);//这个是RelativeLayout的layout_centerInParent属性
linearLayout.setGravity(Gravity.CENTER);//这个是LinearLayout的gravity属性
progressView.addView(linearLayout, paramsLinearLayout);
root.addView(progressView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
}
}
这个类本质是传入一个布局的主ViewGroup,然后里面有3+1种页面可以切换.分别是空页面,错误页面,等待页面和我们的主要内容页面.
这3个页面为了简直,直接用Java代码写布局嵌入了,对外提供showEmptyView(), showErrorView, showProgressView(), showContentView()方法使用
1.为了方便修改.我把可以自定义的文字提醒,大小,图片高宽等都放到开头,拿回去即可修改成项目需要的样式.
2.图片可以找UI切换,随意一点直接用android自带的android.R.drawable.ic_menu_close_clear_cancel和android.R.drawable.ic_menu_search.我随便选的.
使用
package com.yao.statetooldemo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.LinearLayout;
public class MainActivity extends AppCompatActivity {
private StateTool stateTool;
private LinearLayout linearLayout;
private int counter;//演示用的计数器
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
linearLayout = (LinearLayout) findViewById(R.id.linearLayout);
stateTool = new StateTool(linearLayout);
//如果处于错误或者空页面,点击后的事件
stateTool.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
stateTool.showProgressView();//让页面处于progress
doSomeNetwork();//模拟联网操作
}
});
stateTool.showProgressView();//让页面处于progress
doSomeNetwork();//模拟联网操作
}
private void doSomeNetwork(){
AsyncTask<Void, Void, Void> asyncTask = new AsyncTask<Void, Void, Void>() {
//耗时的操作
@Override
protected Void doInBackground(Void... params) {
SystemClock.sleep(1500L);
return null;
}
//耗时操作完成之后,调用这个方法,更新UI
@Override
protected void onPostExecute(Void aVoid) {
if (counter == 0) {
stateTool.showEmptyView();
} else if (counter == 1) {
stateTool.showErrorView();
} else {
stateTool.showContentView();
}
counter++;
}
};
asyncTask.execute();
}
}
使用就简单了,构造函数new StateTool(linearLayout)传主ViewGroup进去.如果主ViewGroup有多个孩子,需要用new StateToo(linearLayout, index)传内容孩子位置的方法.
在你需要联网操作前,调一下stateTool.showProgressView();让它进入等待页面
然后出结果了,调一下相应的空, 错误, 内容页面的方法就行.
StateTool有个点击回调事件,当处于空页面和错误页面点击时,会回调里面的方法.处于正确的内容就当然不会了.