如果移动端访问不佳,请访问 ==> Github 版
关键词:GridView ListView EmptyView SwipeRefreshLayout
在使用 GridView、ListView 时经常需要处理无数据的情况,给用户一些必要的提示。而 GridView 和 ListView 可以使用 setEmptyView()
方法来设置无数据时展示的 View 。
本文讲一下 EmptyView 的基本用法以及如何配合 SwipeRefreshLayout 使用。
背景知识点
FrameLayout 布局方式的特点
FrameLayout 是对其子 View 约束最少最简单的布局,所有放在 FrameLayout 里的控件,都按照层次堆叠在屏幕的左上角。后加进来的控件覆盖前面的控件。
嗯,就像喷漆,后面喷的总是覆盖在之前喷的上面。
setEmptyView()
都做了什么?
setEmptyView(View emptyView)
是 AdapterView
的一个方法,ListView、GridView、Spinner 和 Gallery 都是 AdapterView
的子类,那么理论上来说,本文讲解的针对 ListView、GridView 设置 EmptyView 的方法对于 Spinner、Gallery 应该同样适用。
下面简单看下这个方法的源码:
代码语言:javascript复制public void setEmptyView(View emptyView) {
mEmptyView = emptyView;
// If not explicitly specified this view is important for accessibility.
if (emptyView != null
&& emptyView.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
emptyView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
}
final T adapter = getAdapter();
final boolean empty = ((adapter == null) || adapter.isEmpty());
updateEmptyStatus(empty);
}
/**
* Update the status of the list based on the empty parameter. If empty is true and
* we have an empty view, display it. In all the other cases, make sure that the listview
* is VISIBLE and that the empty view is GONE (if it's not null).
*/
private void updateEmptyStatus(boolean empty) {
if (isInFilterMode()) {
empty = false;
}
if (empty) {
if (mEmptyView != null) {
mEmptyView.setVisibility(View.VISIBLE);
setVisibility(View.GONE);
} else {
// If the caller just removed our empty view, make sure the list view is visible
setVisibility(View.VISIBLE);
}
// We are now GONE, so pending layouts will not be dispatched.
// Force one here to make sure that the state of the list matches
// the state of the adapter.
if (mDataChanged) {
this.onLayout(false, mLeft, mTop, mRight, mBottom);
}
} else {
if (mEmptyView != null) mEmptyView.setVisibility(View.GONE);
setVisibility(View.VISIBLE);
}
}
基本就是:
- 数据为空
setVisibility(View.GONE);
隐藏自身mEmptyView.setVisibility(View.VISIBLE);
显示 EmptyView
- 数据不为空
mEmptyView.setVisibility(View.GONE);
隐藏 EmptyViewsetVisibility(View.VISIBLE);
显示自身
当然,中间还有一些非空判断等。
用法
这里需要说明一点,EmptyView 只要是一个 View 即可,所以除了基本控件(TextView|Button 等)外,也可以是嵌套的布局(LinearLayout|RelativeLayout 等)。
基础用法
布局:
- LinearLayout|FrameLayout|RelativeLayout
- GridView|ListView (id = dataView)
- View(id = mEmptyView , 任意 View,可嵌套)
关键代码:
代码语言:javascript复制@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.xxx);
mDataView = (GridView|ListView) findViewById(R.id.dataView);
adapter = xxxx;
mDataView.setAdapter(adapter);
mDataView.setEmptyView(findViewById(R.id.mEmptyView));
}
PS:务必在 setAdapter()
之后调用 setEmptyView()
。
配合 SwipeRefreshLayout 使用
配合 SwipeRefreshLayout 使用和基础用法类似,唯一需要注意的是布局的嵌套关系。
布局:
- FrameLayout
- SwipeRefreshLayout
- GridView|ListView (id = dataView)
- View( id = mEmptyView ,任意 View,可嵌套)
- SwipeRefreshLayout
关键代码没有变化。这里 GridView|ListView
在 SwipeRefreshLayout
内部,SwipeRefreshLayout
和 EmptyView
需要同级,且最好在 FrameLayout
内部。
总结
本文简单总结了两种最基本的用法,其他更高级更复杂嵌套的情况都可以参考这两种基本用法。
有什么建议或者问题可以随时联系我,共同探讨学习:
- 微博:cafeting
- Github: likfe
- CSDN:他叫自己 Mr. 张