在进行网络请求中,我们希望给用户一个提示,让用户知道正在加载中(就是一个loading动画)。当加载成功或者失败后,我们又能返回对应的结果给用户,让用户一目了然,知道什么原因,之后又可以进一步处理。
1、代码很简单,创建一个类继承FrameLayout
import android.content.Context;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TextView;
public class StatusViewLayout extends FrameLayout {
private View mLoadingView;
private View mErrorView;
private View mEmptyView;
private OnClickListener mOnRetryListener;
private TextView status_view_tv_error;
private TextView status_tv_empty_msg;
public StatusViewLayout(Context context) {
this(context, null);
}
public StatusViewLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public StatusViewLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setUpView();
}
private void setUpView() {
FrameLayout.LayoutParams mLayoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
mLayoutParams.gravity = Gravity.CENTER;
mLoadingView=LayoutInflater.from(getContext()).inflate(R.layout.status_view_layout_loading, null);
mErrorView = LayoutInflater.from(getContext()).inflate(R.layout.status_view_layout_error, null);
mEmptyView = LayoutInflater.from(getContext()).inflate(R.layout.status_view_layout_empty, null);
status_view_tv_error = (TextView) mErrorView.findViewById(R.id.status_view_tv_error);
status_tv_empty_msg = (TextView) mEmptyView.findViewById(R.id.status_tv_empty_msg);
addView(mLoadingView, mLayoutParams);
addView(mErrorView, mLayoutParams);
addView(mEmptyView, mLayoutParams);
mErrorView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (mOnRetryListener != null) {
showLoading();
mOnRetryListener.onClick(view);
}
}
});
mEmptyView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (mOnRetryListener != null) {
showLoading();
mOnRetryListener.onClick(view);
}
}
});
}
public void setOnRetryListener(OnClickListener listener) {
mOnRetryListener = listener;
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
showLoading();
}
public void showLoading() {
for (int i = 0; i < getChildCount(); i++) {
getChildAt(i).setVisibility(View.GONE);
}
mLoadingView.setVisibility(View.VISIBLE);
}
public void showError() {
for (int i = 0; i < getChildCount(); i++) {
getChildAt(i).setVisibility(View.GONE);
}
mErrorView.setVisibility(View.VISIBLE);
}
public void showError(String msg) {
showError();
status_view_tv_error.setText(msg);
}
public void showEmpty() {
for (int i = 0; i < getChildCount(); i++) {
getChildAt(i).setVisibility(View.GONE);
}
mEmptyView.setVisibility(View.VISIBLE);
}
public void showEmpty(String msg) {
showEmpty();
status_tv_empty_msg.setText(msg);
}
public void showContent() {
for (int i = 0; i < getChildCount(); i++) {
getChildAt(i).setVisibility(View.GONE);
}
getChildAt(getChildCount() - 1).setVisibility(View.VISIBLE);
}
}
2、耗时加载的界面中初始化StatusViewLayout
public class MainActivity extends AppCompatActivity {
private StatusViewLayout mStatusView;
private TextView mContent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
/**
* 初始化
*/
private void initView() {
// findView
mStatusView = (StatusViewLayout) findViewById(R.id.main_status_view);
mContent = (TextView) findViewById(R.id.main_content);
// 初始化mStatusView一开始状态为loading
// mStatusView.showLoading();
mStatusView.showContent();
// 当状态为error、empty事件回调
mStatusView.setOnRetryListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
requestData();
}
});
// mContent添加点击事件
mContent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mStatusView.showLoading();
requestData();
}
});
}
/**
* 网络请求
*/
private void requestData() {
String url = "http://gank.io/api/data/Android/50/1";
// ok-go github:https://github.com/jeasonlzy/okhttp-OkGo
OkGo.get(url)
.tag(this)
.execute(new StringCallback() {
@Override
public void onSuccess(String s, Call call, Response response) {
// 解析json
parsingJson(s);
}
@Override
public void onError(Call call, Response response, Exception e) {
super.onError(call, response, e);
// 异常状态
mStatusView.showError();
}
});
}
/**
* 解析json
*
* @param s 请求结果
*/
private void parsingJson(String s) {
try {
JSONObject jsonObject = new JSONObject(s);
if (!jsonObject.getBoolean("error")) {
mStatusView.showContent();
mContent.setText(jsonObject.getJSONArray("results").get(0).toString());
} else
mStatusView.showEmpty();
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
// 取消请求
OkGo.getInstance().cancelTag(this);
}
}
3、xml中,使用StatusViewLayout包裹你的content,StatusViewLayout继承的是FrameLayout,因此可以看作一个FrameLayout布局。
<?xml version="1.0" encoding="utf-8"?>
<com.wz.statusviewdemo.StatusViewLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_status_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.wz.statusviewdemo.MainActivity">
<TextView
android:id="@+id/main_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"/>
</com.wz.statusviewdemo.StatusViewLayout>
4、loading.xml、error.xml和empty.xml可以自己定义
<?xml version="1.0" encoding="utf-8"?>
<!-- loading.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical">
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="30dp"
android:layout_height="30dp"/>
<TextView
android:id="@+id/loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="数据加载中..."
android:textColor="@android:color/darker_gray"
android:textSize="16sp"/>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<!-- error.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/icon_status_error" />
<TextView
android:id="@+id/status_view_tv_error"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="加载出错了"
android:textColor="@android:color/darker_gray"
android:textSize="16sp" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<!-- empty.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/icon_status_empty"/>
<TextView
android:id="@+id/status_tv_empty_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="数据为空"
android:textColor="@android:color/darker_gray"
android:textSize="16sp"/>
</LinearLayout>