在android开发中用到最频繁之一的控件应该算ListView了,虽然现在已经有更强大的控件RecyclerViewl来分担ListView的工作,但对用惯了ListView的人来说还得有一个过渡的阶段,并且有时候使用ListView更为简单些,下面就总结一下ListView的一些属性使用。
ListView是纵向显示条目的控件,条目的内容来自与ListView关联的ListAdapter。
ListView的XML属性
1.ListView的XML属性
- android:divider//在列表条目之间显示的drawable或color
- android:dividerHeight//用来指定divider的高度
- android:entries//构成ListView的数组资源的引用。对于某些固定的资源,这个属性提供了比在程序中添加资源更加简便的方式
- android:footerDividersEnabled//当设为false时,ListView将不会在各个footer之间绘制divider.默认为true。
- android:headerDividersEnabled//当设为false时,ListView将不会在各个header之间绘制divider.默认为true。
2.继承自AbsListView的XML属性
- android:cacheColorHint// 表明这个列表的背景始终以单一、固定的颜色绘制,可以优化绘制过程。
- android:choiceMode//为视图指定选择的行为。可选的类型有:none、singleChoice、multipleChoice、multipleChoiceModal。
- android:drawSelectorOnTop// 若设为true,选择器将绘制在选中条目的上层。默认为false。
- android:fastScrollEnabled// 设置是否允许使用快速滚动滑块。
- android:listSelector// 设置选中项显示的可绘制对象,可以是图片或者颜色属性。
- android:scrollingCache// 设置在滚动时是否使用绘制缓存。若设为true,则将使滚动表现更快速,但会占用更内存。默认为true。
- android:smoothScrollbar// 为真时,列表会使用更精确的基于条目在屏幕上的可见像素高度的计算方法。默认该属性为真,如果你的适配器需要绘制可变高的条目,他应该设为假。当该属性为真时,你在适配器在显示变高条目时,滚动条的把手会在滚动的过程中改变大小。当设为假时,列表只使用适配器中的条目数和屏幕上的可见条目来决定滚动条的属性。
- android:stackFromBottom// 设置GridView和ListView是否将内容从底部开始显示。
- android:textFilterEnabled// 当设为真时,列表会将结果过滤为用户类型。前提是这个列表的Adapter必须支持Filterable接口。
- android:transcriptMode//设置列表的transcriptMode.有如下选项可选:
- //(1)disabled 禁用TranscriptMode,也是默认值;
- //(2)normal 当新条目添加进列表中并且已经准备好显示的时候,列表会自动滑动到底部以显示最新条目;
- //(3)alwaysScroll 列表会自动滑动到底部,无论新条目是否已经准备好显示.
3.继承自ViewGroup的XML属性
- android:addStatesFromChildren// 设置这个ViewGroup的drawable状态是否包括子View的状态。若设为true,当子View如EditText或Button获得焦点时,整个ViewGroup也会获得焦点。
- android:alwaysDrawnWithCache// 设置ViewGroup在绘制子View时是否一直使用绘图缓存。默认为true。
- android:animationCache// 设置布局在绘制动画效果时是否为其子View创建绘图缓存。若设为true,将会消耗更多的内存,要求持续时间更久的初始化过程,但表现更好。默认为true。
- android:clipChildren// 设置子View是否受限于在自己的边界内绘制。若设为false,当子View所占用的空间大于边界时可以绘制在边界外。默认为true。
- android:clipToPadding//定义布局间是否有间距。默认为true。
- android:descendantFocusability// 定义当寻找一个焦点View的时候,ViewGroup与其子View之间的关系。可选项为:
- //(1)beforeDescendants ViewGroup会比其子View更先获得焦点;
- //(2)afterDescendants 只有当无子View想要获取焦点时,ViewGroup才会获取焦点;
- //(3)blockDescendants ViewGroup会阻止子View获取焦点
- android:layoutAnimation//定义当ViewGroup第一次展开时的动画效果,也可人为地在第一次展开后调用。
- android:persistentDrawingCache// 定义绘图缓存的持久性。有如下可选项:
- //(1)none 当使用过后不保留绘图缓存
- //(2)animation 在layout animation之后保留绘图缓存
- //(3)scrolling 在Scroll操作后保留绘图缓存
- //(4)all always保留绘图缓存
常用public方法
1.add/remove 方法
- void addFooterView(View v)//增加一个固定在列表底部的View,参数 v为欲添加的视图
- void addFooterView(View v,Object data,boolean isSelectable)//增加一个固定在列表底部的View,参数 v为欲添加的视图,data为与View绑定的数据,isSelectable设置是否可选
- void addHeaderView(View v)//增加一个固定在列表顶部的View,参数 v为欲添加的视图
- void addHeaderView(View v,Object data,boolean isSelectable)//增加一个固定在列表顶部的View,参数 v为欲添加的视图,data为与View绑定的数据,isSelectable设置是否可选
- boolean removeFooterView(View v)//去除一个之前添加的FooterView,参数v为欲删除的视图,若成功删除则返回true
- boolean removeHeaderView(View v)//去除一个之前添加的HeaderView,参数v为欲删除的视图,若成功删除则返回true
2.响应事件方法
- boolean OnKeyDown(int keyCode,KeyEvent event)//当按下键时响应
- boolean OnKeyMultiple(int keyCode,int repeatCount,KeyEvent event)//重复按下键时响应,repeatCount为按下次数
- boolean OnKeyUp(int keyCode,KeyEvent event)//当键被释放时响应
3.get方法
- ListAdapter getAdapter()//返回ListView正在使用的Adapter
- Drawable getDivider()//以Drawable形式返回divider
- int getDividerHeight()//这个……真不想解释了
- int getFooterViewCount()//返回FooterView的个数,若无返回0
- int getHeaderViewCount()//返回HeaderView的个数,若无返回0
- boolean getItemsCanFocus()//返回是否有可获得焦点的条目
- int getMaxScrollAmount()//The maximum amount a list view will scroll in response to an arrow event.(求翻译)
- Drawable getOverscrollFooter()//返回绘制在所有条目之下的drawable
- Drawable getOverscrollHeader()//返回绘制在所有条目之上的drawable
4.set方法
- void setAdapter(ListAdapter adapter)//为ListView绑定Adapter
- void setCacheColorHint(int color)//参数为0时,将CacheColor设为透明;参数非零时,指定一种颜色作为ListView的背景
- void setDivider(Drawable divider)//为ListView中每个条目之间设定一个Divider
- void setDividerHeight(int height)//设定Divider的高度,单位为pixel
- void setFooterDividerEnabled(boolean footDividerEnabled)//设置FooterView之间的Dividers是否可用
- void setHeaderDividerEnabled(boolean headDividerEnabled)//设置HeaderView之间的Dividers是否可用
- void setItemsCanFocus(boolean itemsCanFocus)//设置是否包含可获取焦点的Item
- void setOverscrollFooter(Drawable footer)//设置一个当滚动时或ListView未填满屏幕时能显示在ListView下方的Drawable
- void setOverscrollHeader(Drawable header)//设置一个当滚动时能显示在ListView上方的Drawable
- void setRemoteViewAdapter(Intent intent)//为此AbsListView设置一个通过intent连接到RemoteViewsService而提供的远程视图适配器
- void setSelection(int position)//设置被选中的条目。如果参数小于0,则position为0的条目将被选中
- void setSelectionAfterHeaderView()//选中headerView下方的第一条条目
一、stackFromBottom
若把ListView的XML属性android:stackFromBottom设为"true",则ListView中的内容将从底部开始显示。效果如图:
二、cacheColorHint
当你在点击ListView或者拖动它的时候,是不是发现ListView中的条目变黑了?这点大大影响了整体UI的和谐统一。其实解决方法很简单,利用ListView的父类AbsListView提供的XML属性----android:cacheColorHint就可以解决。cacheColorHint表明列表将始终以单一、固定的颜色来绘制背景,如果想与整体的背景色统一,只需要将其设为透明(#00000000)即可。
运行效果见下一个属性。
三、scrollBars
当你需要一个快速滑动条时,android:scrollBars属性就可以满足你的需要。
将android:scrollBars='Vertical'与调用ListView的方法setVerticalScrollBarEnabled(true)效果是一样的。
如图所示:
可以注意到屏幕右侧出现了快速滚动条,另外,在滚动时ListView没有变成黑色,就是因为设置了属性android:cacheColorHint="#00000000".
如果你需要让ScrollBar一直显示,可以调用ListView的方法setScrollBarFaddingEnabled(false);
如果你需要让ScrollBar在滚动时显示,并在滚动结束时一段时间后自动消失,可以设置XML属性----android:scrollBarFadeDuration="500",500表示在滚动后500毫秒后ScrollBar消失
Ps:哪位大神可以告诉我android:fastScrollEnabled与ScrollBars有何区别
四、footerView和headerView
1. 可随ListView滚动的footView和headView
(1)创建HeaderView的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:orientation="vertical" >
- <TextView
- android:id="@+id/headertext"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="#000000" />
- </LinearLayout>
(2)在Activity方法中添加以下代码(只添加了setHeaderandFooter方法,可以根据上下文自行理解):
- private void setHeaderandFooter() {
- LayoutInflater lif = LayoutInflater.from(this);
- try {
- View headerView = lif.inflate(R.layout.header, myListView, false);
- TextView header = (TextView) headerView.findViewById(R.id.headertext);
- header.setText("HeaderView");
- myListView.addHeaderView(headerView);
- } catch (Exception e) {
- // TODO: handle exception
- Log.v("List", e.getMessage());
- }
- }
(3)运行结果:
(4)需要注意的地方
第一点是addHeaderView必须在setAdapter之前调用,否则headerview将不会显示出来。
在这里需要注意的第二点是,添加完headerView之后,会导致OnItemClickListener等监听器的position移位。
例如,我处理点击事件的代码为:
- myListView.setOnItemClickListener(new OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
- long arg3) {
- // TODO Auto-generated method stub
- new AlertDialog.Builder(ListViewTestActivity.this)
- .setMessage("Clicked Line No." + arg2)
- .setPositiveButton("Confirm", null).show();
- }
- });
而当我点击了显示数字0的那一条,结果为:
可以看出position将headerview也计入在内了,这显然不是我们所预期的结果。为了解决这个问题,在此提供一种解决方法:
手动计算真实的position
- final int headerCount = myListView.getHeaderViewsCount();
- myListView.setOnItemClickListener(new OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
- long arg3) {
- // TODO Auto-generated method stub
- new AlertDialog.Builder(ListViewTestActivity.this)
- .setMessage("Clicked Line No." + (arg2 - headerCount))
- .setPositiveButton("Confirm", null).show();
- }
- });
2.固定的HeaderView
固定的HeaderView,即不随ListView滚动的HeaderView。实现效果如下:
其实做法很简单,但是有一些小细节需要注意。
首先来看main.xml
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:background="#58ACFA"
- android:orientation="vertical" >
- <include layout="@layout/header" />
- <ListView
- android:id="@+id/myListView"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:cacheColorHint="#00000000"
- android:fastScrollEnabled="true"
- android:scrollbarFadeDuration="1000"
- android:scrollbarStyle="outsideOverlay" >
- </ListView>
- </LinearLayout>
header.xml
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="vertical" >
- <TextView
- android:id="@+id/headertext"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="#000000"
- android:text="HeaderText" />
- </LinearLayout>
在此需要注意,header中的LinearLayout的 layout_height一旦设为"fill_parents"将会使得ListView无法显示出来 。(为此纠结了好久……)
而以这种方式添加headerView的话,OnItemClickListener中的position就不会发生移位现象了,因为严格意义上来说,这里的headerView并不属于ListView这个ViewGroup中,而是另外一个独立的布局。
据了解,listview每行的高度是由 inflater填充布局中高度最大的那个控件来决定的。
那怎么办?
在item的layout文件中,给item设定minHeight,即可。请如下黑色粗体所示:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" android:minHeight="100dp" > <TextView android:id="@+id/textView01" android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="@string/hello" /> </LinearLayout>