寫在前面
在平時(shí)的開發(fā)之中,我們需要對(duì)于數(shù)據(jù)加載的情況進(jìn)行展示:
現(xiàn)在設(shè)置頁面狀態(tài)的方式有多種,由于筆者近期一直在使用databinding,而數(shù)據(jù)綁定通過改變模型來展示view的方式和狀態(tài)頁的設(shè)置也滿契合的。
所以這里就講講使用databinding來設(shè)置android中的各種狀態(tài)頁。很簡(jiǎn)單,先看看效果

首先
在app的build.gradle文件中開啟databinding
android{ ... dataBinding { enabled = true }}我們先定義一些用于狀態(tài)的注解EmptyState
/** * 頁面描述:空狀態(tài) * <p> * Created by ditclear on 2017/2/24. */@IntDef({NORMAL, PROGRESS, EMPTY, NET_ERROR, NOT_AVAILABLE})@Retention(RetentionPolicy.SOURCE)public @interface EmptyState { int NORMAL = -1; //正常 int PROGRESS = -2;//顯示進(jìn)度條 int EMPTY = 11111; //列表數(shù)據(jù)為空 int NET_ERROR = 22222; //網(wǎng)絡(luò)未連接 int NOT_AVAILABLE = 33333; //服務(wù)器不可用 //...各種頁面的空狀態(tài),可以自己定義、添加}再自定義一個(gè)異常EmptyException用于顯示我們需要的狀態(tài)信息
/** * 頁面描述:異常 * <p> * Created by ditclear on 2017/3/5. */public class EmptyException extends Exception { private int code; public EmptyException(@EmptyState int code) { super(); this.code = code; } @EmptyState public int getCode() { return code; } public void setCode(@EmptyState int code) { this.code = code; }}現(xiàn)在,大多數(shù)展示狀態(tài)頁的控件都會(huì)提供
所以我們的目標(biāo)也是顯示這些
布局
以數(shù)據(jù)綁定的形式進(jìn)行布局,使用StateModel來控制狀態(tài)頁展示的消息
<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android" > <data> <import type="android.view.View"/> <variable name="stateModel" type="com.ditclear.app.state.StateModel"/> </data> <RelativeLayout android:id="@+id/rv_empty_view" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/background" android:clickable="true" android:focusableInTouchMode="true" android:visibility="@{stateModel.empty?View.VISIBLE:View.GONE}"> <android.support.v4.widget.ContentLoadingProgressBar style="?android:attr/progressBarStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:visibility="@{stateModel.progress?View.VISIBLE:View.GONE}"/> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:gravity="center" android:orientation="vertical" android:visibility="@{stateModel.progress?View.INVISIBLE:View.VISIBLE}"> <ImageView android:id="@+id/none_data" android:layout_width="345dp" android:layout_height="180dp" android:scaleType="fitCenter" android:src="@{stateModel.emptyIconRes}"/> <TextView android:layout_width="wrap_content" android:layout_height="25dp" android:layout_below="@+id/none_data" android:layout_centerHorizontal="true" android:text="@{stateModel.currentStateLabel}" android:textSize="16sp"/> </LinearLayout> </RelativeLayout></layout>布局文件中有幾個(gè)方法
我們定義狀態(tài)的ViewModel ,就叫StateModel,來控制狀態(tài)
/** * 頁面描述:狀態(tài)頁面設(shè)置模型 * <p> * Created by ditclear on 2017/2/24. */public class StateModel extends BaseObservable { private Context mContext = MyApp.instance(); @EmptyState private int emptyState = EmptyState.NORMAL; private boolean empty; public int getEmptyState() { return emptyState; } /** * 設(shè)置狀態(tài) * * @param emptyState */ public void setEmptyState(@EmptyState int emptyState) { this.emptyState = emptyState; notifyChange(); } /** * 顯示進(jìn)度條 * * @return */ public boolean isProgress() { return this.emptyState == EmptyState.PROGRESS; } /** * 根據(jù)異常顯示狀態(tài) * * @param e */ public void bindThrowable(Throwable e) { if (e instanceof EmptyException) { @EmptyState int code = ((EmptyException) e).getCode(); setEmptyState(code); } } public boolean isEmpty() { return this.emptyState != EmptyState.NORMAL; } /** * 空狀態(tài)信息 * * @return */ @Bindable public String getCurrentStateLabel() { switch (emptyState) { case EmptyState.EMPTY: return mContext.getString(R.string.no_data); case EmptyState.NET_ERROR: return mContext.getString(R.string.please_check_net_state); case EmptyState.NOT_AVAILABLE: return mContext.getString(R.string.server_not_avaliabe); default: return mContext.getString(R.string.no_data); } } /** * 空狀態(tài)圖片 * * @return */ @Bindable public Drawable getEmptyIconRes() { switch (emptyState) { case EmptyState.EMPTY: return ContextCompat.getDrawable(mContext, R.drawable.ic_visibility_off_green_400_48dp); case EmptyState.NET_ERROR: return ContextCompat.getDrawable(mContext, R.drawable.ic_signal_wifi_off_green_400_48dp); case EmptyState.NOT_AVAILABLE: return ContextCompat.getDrawable(mContext, R.drawable.ic_cloud_off_green_400_48dp); default: return ContextCompat.getDrawable(mContext, R.drawable.ic_visibility_off_green_400_48dp); } }}很普通的視圖模型,主要有幾個(gè)用于判斷狀態(tài)顯示的方法
下面講講實(shí)際運(yùn)用:
在activity或者fragment布局中,添加狀態(tài)頁的布局
<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> <import type="android.view.View"/> <variable name="stateModel" type="com.ditclear.app.state.StateModel"/> </data> <com.ditclear.app.ScrollChildSwipeRefreshLayout android:id="@+id/refresh_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <RelativeLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="false" android:overScrollMode="always" android:visibility="@{stateModel.empty?View.GONE:View.VISIBLE}"> <TextView android:id="@+id/content_tv" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center"/> </android.support.v4.widget.NestedScrollView> <include layout="@layout/widget_layout_empty" app:stateModel="@{stateModel}"/> </RelativeLayout> </com.ditclear.app.ScrollChildSwipeRefreshLayout></layout>最后在activity或者fragment中我們只需要通過state.bindThrowable()和state.setEmptyState()方法便可以輕松設(shè)置各種各樣的狀態(tài)。
loadData().subscribe(new Subscriber<List<Contributor>>() { @Override public void onStart() { super.onStart(); if (!mMainBinding.refreshLayout.isRefreshing()) { mStateModel.setEmptyState(EmptyState.PROGRESS); } } @Override public void onCompleted() { mStateModel.setEmptyState(EmptyState.NORMAL); } @Override public void onError(Throwable e) { mMainBinding.refreshLayout.setRefreshing(false); mStateModel.bindThrowable(e); Toast.makeText(MainActivity.this, mStateModel.getCurrentStateLabel(), Toast.LENGTH_SHORT).show(); } @Override public void onNext(List<Contributor> contributors) { mMainBinding.refreshLayout.setRefreshing(false); if (contributors == null || contributors.isEmpty()) { onError(new EmptyException(EmptyState.EMPTY)); } else { mMainBinding.contentTv.setText(contributors.toString()); } }});寫在最后
對(duì)于要使用數(shù)據(jù)來控制視圖狀態(tài)的,使用databinding實(shí)在是一個(gè)事半功倍的方式。而且也十分容易理解。
最后demo地址:StateBinding.rar
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持VEVB武林網(wǎng)。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注