android 空布局,Android通用的EmptyLayout-展示不用狀態的界面

前言

在做項目的時候,經常會遇到列表數據為空的時候展示的空布局,如果你用的是ListView ,目測會經常使用ListView的一個方法setEmptyView ,如果你用的是RecyclerView,你也許會用自定義View來實現,但是,這些方法雖然使用起來簡單,但是如果你提供一個復雜的布局,例如:

在數據加載失敗后,添加一個Button讓用戶可以選擇重新加載數據。

你肯定會說,findviewbyId找到這個button,給它設置點擊事件,一個兩個可以接受,但是,界面多了呢? 那你說了那么多,有沒有好的解決辦法呢? 當然有 而且是幾行代碼搞定的

自定義View

接下來就是重頭戲 開始編碼了 ,首先我們需要繼承FrameLayout來實現這樣的布局

123456789101112131415

public class EmptyLayout extends FrameLayout{public EmptyLayout(Context context){this(context, null);}public EmptyLayout(Context context, AttributeSet attrs){this(context, attrs, 0);}public EmptyLayout(Context context, AttributeSet attrs, int defStyleAttr){}}

為了靈活性,我自定義屬性來添加所需要的布局,values下面新建attrs.xml

12345678

然后我們以此找到這些布局,並且添加進去

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061

public class EmptyLayout extends FrameLayout{private Context mContext;private View mEmptyView;private View mBindView;private View mErrorView;private Button mBtnReset;private View mLoadingView;private View loadingView;private TextView mEmptyText;private TextView tvLoadingText;public EmptyLayout(Context context){this(context, null);}public EmptyLayout(Context context, AttributeSet attrs){this(context, attrs, 0);}public EmptyLayout(Context context, AttributeSet attrs, int defStyleAttr){super(context, attrs, defStyleAttr);this.mContext=context;LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);//居中params.gravity = Gravity.CENTER;TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.EmptyLayout, 0, 0);//數據為空時的布局int emptyLayout = ta.getResourceId(R.styleable.EmptyLayout_elEmptyLayout, R.layout.layout_empty);mEmptyView = View.inflate(context, emptyLayout, null);mEmptyText =(TextView)mEmptyView.findViewById(R.id.tvEmptyText);addView(mEmptyView,params);//加載中的布局int loadingLayout = ta.getResourceId(R.styleable.EmptyLayout_elLoadingLayout, R.layout.layout_loading);mLoadingView = View.inflate(context, loadingLayout, null);tvLoadingText =(TextView)mLoadingView.findViewById(R.id.tvLoadingText);addView(mLoadingView,params);//錯誤時的布局int errorLayout = ta.getResourceId(R.styleable.EmptyLayout_elErrorLayout, R.layout.layout_error);mErrorView = View.inflate(context, errorLayout, null);mBtnReset =(Button)mErrorView.findViewById(R.id.btnReset);addView(mErrorView, params);//全部隱藏setGone();}/*** 全部隱藏*/private void setGone(){mEmptyView.setVisibility(View.GONE);mErrorView.setVisibility(View.GONE);mLoadingView.setVisibility(View.GONE);}}

簡單說下幾個變量的作用

mEmptyView 表示數據為空的時候展示給用戶

mEmptyText 數據為空提示的文字

mErrorView 加載錯誤展示給用戶

mBtnReset 加載錯誤重新加載的按鈕

mLoadingView 加載中展示給用戶

tvLoadingText 加載中提示的文字

mBindView 我們要綁定的view

好了,首先我們找到布局,然后添加進去,如果沒有,添加默認的布局。至此,布局已經完成,那怎么控制呢?我們想要的是什么效果呢?

在數據正在加載的時候調用loading方法,顯示正在加載中的文本。

在數據加載成,隱藏該view。

在數據加載失敗,顯示加載失敗的文本,並提供一個按鈕去刷新數據。

ok,我們按照這個條目一個個的來實現,首先是loading。

1234567891011

public void showLoading(String text){if (mBindView != null) mBindView.setVisibility(View.GONE);if (!TextUtils.isEmpty(text)) tvLoadingText.setText(text);setGone();mLoadingView.setVisibility(View.VISIBLE);}public void showLoading(){showLoading(null);}

首先判斷下我們要綁定view是不是為空,不為空則隱藏它,隱藏其他布局,然后展示loadingview

那加載失敗了呢?同樣簡單!

12345678910

public void showError(){showError(null);}public void showError(String text){if (mBindView != null) mBindView.setVisibility(View.GONE);if (!TextUtils.isEmpty(text)) mBtnReset.setText(text);setGone();mErrorView.setVisibility(View.VISIBLE);}

這個同上

繼續看看加載成功的方法,這個更簡單啦。

12345

public void showSuccess(){if (mBindView != null) mBindView.setVisibility(View.VISIBLE);setGone();}

至此,我們整個效果就完成了,在加載數據的時候調用showLoading方法來顯示加載中的文本,加載失敗后,調用showError來顯示加載失敗的文本和刷新的按鈕,在加載成功后直接隱藏控件

控件倒是完成了,我們還不知道mBindView怎么來的,其實也很簡單。我們在代碼中需要調用bindView(View view)方法來指定。

1234

public void bindView(View view){mBindView = view;}

那么問題來了,我加載失敗后,按鈕的點擊事件怎么做呢?有人會說用反射,這樣既省了代碼行數,看着又舒服,但是這樣是有個問題存在的,大家都知道,一個項目的上線,都會進行混淆代碼的,為了就是防止他人剽竊我們的勞動成果,可是混淆過后哪些class全部變成a,b,c ,這樣如果用反射的話就會導致點擊事件失效,因為找不到這個類,所以,我們還是老老實實的用onclick事件吧

1234

public void setOnButtonClick(OnClickListener listener){mBtnReset.setOnClickListener(listener);}

這樣,一個簡單的EmptyLayout就誕生了,接下來我們來看看怎么使用

先看xml布局

123456789101112131415161718192021222324

在看看Activity中怎么調用

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859

public class MainActivity extends Activity{private EmptyLayout emptyLayout;private RecyclerView recyclerView;private List list = new ArrayList<>();private MyAdapter adapter;@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();loadData();}private Handler mHandler = new Handler();private void initView(){emptyLayout = (EmptyLayout) findViewById(R.id.emptyLayout);recyclerView = (RecyclerView) findViewById(R.id.recyclerView);recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));recyclerView.setAdapter(adapter = new MyAdapter(list));//綁定emptyLayout.bindView(recyclerView);emptyLayout.setOnButtonClick(new View.OnClickListener() {@Overridepublic void onClick(View v){//重新加載數據loadData();}});}private void loadData(){//模擬加載數據emptyLayout.showLoading("正在加載,請稍后");mHandler.postDelayed(new Runnable() {@Overridepublic void run(){Random r = new Random();int res = r.nextInt(10);if (res % 2 == 0) {// 失敗emptyLayout.showError("加載失敗,點擊重新加載"); // 顯示失敗} else {// 成功emptyLayout.showSuccess();for (int i = 0; i < 15; i++) {list.add("測試" + i);}adapter.notifyDataSetChanged();}}}, 3000);}}

首頁我們找到控件,然后給recyclerView設置adapter,然后我們調用emptyLayout.bindView(recyclerView);來設置要綁定的view,當然這里是recyclerView,接下來,通過emptyLayout.setOnButtonClick()來設置重新加載的時候執行哪個方法,在loadData()中延遲3秒獲取數據,數據成功失敗都是隨機的,當失敗的時候會調用emptyLayout.showError(),成功就調用emptyLayout.showSuccess();就這么簡單,來看看運行效果

效果展示

aHR0cDovL3d3dy53ZXl5ZS5tZS9pbWcvZGV2aWNlLTIwMTYtMDgtMzAtMTgwMDU2JTIwMDBfMDBfMDAtMDBfMDBfMTB+MS5naWY=

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值