一天一Android之ListView
说起ListView
,就不得不说iOS的UITableView
,毫不夸张的说的,放在3年前,如果你去面试的时候,你说你会用UITableView
,知道UITableView
的代理方法,不用说了,你可以直接来上班了。
ListView
在Android中开发的重要性不言而喻,学好ListView
,我想在以后的列表开发中就不用发愁了。什么是列表开发?这么说吧,在你使用的APP中,80%的都会用到列表开发,比如微信的聊天页,QQ的个人空间页。为何要用列表开发,列表开发的优越在哪里?我今天来一探究竟。
ListView初体验
我们先来写个小例子,根据这个小例子我们再做进一步的介绍。我们先在xml中创建一个ListView,这里我直接使用ConstraintLayout
约束布局。
|
MainActivity的代码:
|
运行如下:
ListView
在Android所有常用的原生控件当中,用法最复杂的应该就是ListView了,它专门用于处理那种内容元素很多,手机屏幕无法展示出所有内容的情况。ListView可以使用列表的形式来展示内容,超出屏幕部分的内容只需要通过手指滑动就可以移动到屏幕内了。
我们先看看ListView的继承体系:
属性
android:divider
在列表条目之间显示的图片或者颜色(drawable或color)android:dividerHeight
用来指定divider的高度android:scrollbars
设置滚动条状态,不需要滚动条时,设置为noneandroid:listSelector
设置条目选中后的颜色,可设置为#00000000或者@android:color/transparent 取消选中色android:footerDividersEnabled
当设置为false时,ListView将不会在各个footer之间绘制divider,默认为trueandroid:headerDividersEnabled
当设为false时,ListView将不会在各个header之间绘制divider,默认为true
其他继承父类的属性就不说了。
方法
void addFooterView(View v)
添加一个固定在列表底部的Viewboolean removeFooterView(View v)
删除一个之前添加的FooterView,参数为欲删除的视图,返回是否删除成功void addHeaderView(View v)
添加一个固定在列表顶部的Viewboolean removeHeaderView(View v)
删除一个之前添加的HeaderView,参数为欲删除的视图,返回是否删除成功void setAdapter(ListAdapter adapter)
为ListView绑定AdapterListAdapter getAdapter()
返回ListView正在使用的Adaptervoid setEmptyView(View emptyView)
当数据的个数为0的时候显示一个提示视图
通过上面一个简单的例子我们可以看出,ListView如果想要显示数据,必须需要一个Adapter来适配。Android为什么这么设计呢?如果学习过iOS的同学都知道,我们在使用UITableView的时候,一定会实现它的数据源代理方法,在代理方法中我们会返回条目数和条目View。这种设计方法有效的分离了UITableView和数据源的直接打交道,让数据源的显示交于用户来选择。Android也是如此。
ListView只承担交互和展示工作,至于这些数据来源于哪里,ListView并不关心。于是就有了Adapter这样一个机制的出现。Adapter是适配器的意思,它在ListView和数据源之间起到了一个桥梁的作用,ListView会借助Adapter这个桥梁去访问真正的数据源,因为Adapter的接口都是统一的,因此我们可以通过实现接口来定制各种类型的Adapter。另外系统也为我们实现了一些常用的Adapter,比如我们上面用到的ArrayAdapter等。
Adapter
我们先来看看继承体系:
Adapter定义的抽象函数主要包括:
void registerDataSetObserver(DataSetObserver observer)
添加数据源变化的observer,如增加、删除等将会执行void unregisterDataSetObserver(DataSetObserver observer)
取消注册的observerint getCount()
显示有多少个数据项 即adapter有多少个条目Object getItem(int position)
返回数据集中position位置所对应的数据项long getItemId(int position)
返回position位置所对应的ID号,通常即为positionView getView(int position, View convertView, ViewGroup parent)
核心函数,返回position数据项对应的条目View
上个示例我们使用的ArrayAdapter,他只能用来显示TextView,如果我们想显示更多的不同种类的条目,我们需要继承BaseAdapter
,并重写相关方法,我们现在来看看如何重写。
先上示例图:
我们新建一个Dog类,有name
和imageId
两个成员变量,分别表示狗的名字和图片资源(这里使用本地图片):
|
我们在新建一个DogAdapter继承于ArrayAdapter
|
注意:我们都知道ListView的强大,它强大就强大在无论我们设置多少条数据源,ListView都不会完全的把这些条目都创建,而是通过复用已经消失在屏幕的条目来展示新的条目。
在getView
函数中,有个convertView
参数,如果它不为空,就表示ListView的缓存池中有可复用的条目,我们直接取来用就行。而且我们还创建了一个内部类ViewHolder
,声明了两个属性mImageView
和mTextView
,我们可以给View设置tag,方便下次给View赋值的时候,不需要再次调用findViewById
方法来重新查找属性。
再来看我们如何使用DogAdapter:
|
其他方法
触摸监听 OnTouchListener
|
滑动监听 OnScrollListener
|
条目点击 OnItemClickListener
|
仿微信聊天界面
说了这么多,再来做一个例子,仿一下微信的聊天界面。
先看布局,这里依旧使用约束布局:
ListView布局
|
item布局
这里我们把两种布局都定义在一个xml文件中,稍后会根据代码来决定隐藏哪种类型。
|
消息实体 MSG类
我们再创建一个消息实体,来存储消息信息。这里我们定义了两种消息类型,TYPE_RECEIVED
表示接收的消息,TYPE_SENT
表示发送的消息。
|
消息适配器 WXMsgAdapter
重点来了,我们会根据消息的类型来决定显示哪种布局方式。
|
我们在WXChatActivity中这样用:
|
运行结果如下:
小结
写完微信的小例子,心里的成就感还是很强的,ListView的强大还远不止如此,因为我知道iOS的UITableView的重要性,相信在以后的开发中我会经常和ListView打交道的。