一般情况下,空白界面和网络错误界面是不用显示的,所以用ViewStub,减少内存消耗。
1.准备四种view的布局
1)status_empty.xml 数据空白界面
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical"> <Button android:id="@+id/btn_status_empty" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="数据空白,重新加载" /> </LinearLayout>2)status_loading.xml 加载中界面
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:background="@color/colorPrimary" android:orientation="vertical"> <ProgressBar android:id="@+id/progressBar" style="?android:attr/progressBarStyle" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
3)status_error.xml 网络错误界面
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical"> <Button android:id="@+id/btn_status_error" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="网路错误,重新加载" /> </LinearLayout>
4)success.xml 数据加载成功界面
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:text="成功加载" /> </LinearLayout>
2.根布局 status_view.xml
<?xml version="1.0" encoding="utf-8"?> <merge xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <include android:id="@+id/status_loading" layout="@layout/status_loading" android:layout_width="match_parent" android:layout_height="match_parent" /> <ViewStub android:id="@+id/stub_empty" android:layout_width="match_parent" android:layout_height="match_parent" android:inflatedId="@+id/status_empty" android:layout="@layout/status_empty" /> <ViewStub android:id="@+id/stub_error" android:layout_width="match_parent" android:layout_height="match_parent" android:inflatedId="@+id/status_error" android:layout="@layout/status_error" /> </merge>
3.自定义StatusView
public class StatusView extends FrameLayout { private static final String TAG = "StatusView"; /** * 四种状态 */ public static final int LOADING = 1; public static final int ERROR = 2; public static final int EMPTY = 3; public static final int SUCCESS = 4; private FrameLayout mRootView; private View mLoadingView; private View mEmptyView; private View mErrorView; private View mSuccessView; //刷新按钮 private Button mBtnEmptyRefresh, mBtnErrorRefresh; public StatusView(@NonNull Context context) { super(context, null); } public StatusView(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); initView(context); } public StatusView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); initView(context); } private void initView(Context context) { mRootView = (FrameLayout) LayoutInflater.from(context).inflate(R.layout.status_view, this); initLoadView(); } private void initLoadView() { mLoadingView = mRootView.findViewById(R.id.status_loading); } public void setSuccessView(int id) { if (mSuccessView == null) { mSuccessView = LayoutInflater.from(getContext()).inflate(id, null); FrameLayout.LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); mRootView.addView(mSuccessView, 0, layoutParams);//放到FrameLayout第一个位置 } } /** * View的切换 * @param status */ public void showStatusView(int status) { Log.d(TAG, "showStatusView: status==" + status); switch (status) { case EMPTY: showEmptyView(); break; case ERROR: showErrorView(); break; case LOADING: showLoadingView(); break; case SUCCESS: showSuccessView(); break; default: showLoadingView(); break; } } private void showLoadingView() { if (mLoadingView != null) { mLoadingView.setVisibility(VISIBLE); } dismissErrorView(); dismissEmptyView(); dismissSuccessView(); } private void showEmptyView() { ViewStub stub = (ViewStub) mRootView.findViewById(R.id.stub_empty); if (stub != null) { mEmptyView = stub.inflate();//ViewStub调用inflate()方法后,R.id.stub_empty这个id会从布局中移除 mBtnEmptyRefresh = (Button) mEmptyView.findViewById(R.id.btn_status_empty); mBtnEmptyRefresh.setOnClickListener(mOnClickListener); } else { mEmptyView.setVisibility(VISIBLE); } dismissErrorView(); dismissLoadingView(); dismissSuccessView(); } private void showErrorView() { ViewStub stub = (ViewStub) mRootView.findViewById(R.id.stub_error); if (stub != null) { mErrorView = stub.inflate(); mBtnErrorRefresh = (Button) findViewById(R.id.btn_status_error); mBtnErrorRefresh.setOnClickListener(mOnClickListener); } else { mErrorView.setVisibility(VISIBLE); } dismissLoadingView(); dismissEmptyView(); dismissSuccessView(); } private void showSuccessView() { if (mSuccessView != null) { mSuccessView.setVisibility(VISIBLE); dismissEmptyView(); dismissLoadingView(); dismissErrorView(); } } private void dismissLoadingView() { if (mLoadingView != null && mLoadingView.getVisibility() == VISIBLE) { mLoadingView.setVisibility(GONE); } } private void dismissEmptyView() { if (mEmptyView != null && mEmptyView.getVisibility() == VISIBLE) { mEmptyView.setVisibility(GONE); } } private void dismissErrorView() { if (mErrorView != null && mErrorView.getVisibility() == VISIBLE) { mErrorView.setVisibility(GONE); } } private void dismissSuccessView() { if (mSuccessView != null && mSuccessView.getVisibility() == VISIBLE) { mSuccessView.setVisibility(GONE); } } private OnClickListener mOnClickListener = new OnClickListener() { @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_status_empty: case R.id.btn_status_error: if (mOnRetryGetDataListener != null) { mOnRetryGetDataListener.refresh(); } break; } } }; /** * 点击重新加载 */ public interface OnRetryGetDataListener { void refresh(); } private OnRetryGetDataListener mOnRetryGetDataListener; public void setOnRetryGetDataListener(OnRetryGetDataListener onRetryGetDataListener) { if (onRetryGetDataListener != null) { mOnRetryGetDataListener = onRetryGetDataListener; } } }
4.StatusView的使用
1)测试的布局activity_test_status_view.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.example.testretrofitrxjava.TestStatusViewActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/btn_loading" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="加载中" /> <Button android:id="@+id/btn_empty" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="空白" /> <Button android:id="@+id/btn_net_error" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="网络错误" /> <Button android:id="@+id/btn_success" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="成功" /> </LinearLayout> <com.example.testretrofitrxjava.widget.StatusView android:id="@+id/status_view" android:layout_width="match_parent" android:layout_height="match_parent"></com.example.testretrofitrxjava.widget.StatusView> </LinearLayout>
2)测试的Activity
public class TestStatusViewActivity extends AppCompatActivity { private static final String TAG = "TestStatusViewActivity"; private Button mBtnLoading, mBtnEmpty, mBtnError, mBtnSuccess; private StatusView mStatusView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test_status_view); initView(); } private void initView() { mBtnLoading = (Button) findViewById(R.id.btn_loading); mBtnLoading.setOnClickListener(mOnClickListener); mBtnEmpty = (Button) findViewById(R.id.btn_empty); mBtnEmpty.setOnClickListener(mOnClickListener); mBtnError = (Button) findViewById(R.id.btn_net_error); mBtnError.setOnClickListener(mOnClickListener); mBtnSuccess = (Button) findViewById(R.id.btn_success); mBtnSuccess.setOnClickListener(mOnClickListener); mStatusView = (StatusView) findViewById(R.id.status_view); mStatusView.setSuccessView(R.layout.success); mStatusView.setOnRetryGetDataListener(new StatusView.OnRetryGetDataListener() { @Override public void refresh() { Log.e(TAG, "refresh: 数据重新加载"); } }); } private View.OnClickListener mOnClickListener = new View.OnClickListener() { @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_loading: mStatusView.showStatusView(StatusView.LOADING); break; case R.id.btn_empty: mStatusView.showStatusView(StatusView.EMPTY); break; case R.id.btn_net_error: mStatusView.showStatusView(StatusView.ERROR); break; case R.id.btn_success: mStatusView.showStatusView(StatusView.SUCCESS); break; default: break; } } }; }