< ListVIew,作为Android常用控件之一,是一个用来纵向显示条目的视图,这些条目内容来自于与该ListView相关联的ListAdapter。
1.继承关系
<span style="white-space:pre"> </span>java.lang.Object
android.view.View
android.view.ViewGroup
android.widget.AdapterView<android.widget.ListAdapter>
android.widget.AbsListView
android.widget.ListView</span>
2.直接子类
ExpandableListView
3.嵌套类
class ListView.FixedViewInfo//用来在列表内展现一个固定位置视图,如在列表顶端的header和在列表底端的footer
4.XML属性
4.1 ListView的XML属性
<span style="font-family:SimSun;font-size:14px;"><span style="white-space:pre"> </span>android:fadingEdge="none" // 上边和下边有黑色的阴影,设置为None后阴影消失
<span style="white-space:pre"> </span>android:scrollbars="none" // 隐藏listView的滚动条
android:drawSelectorOnTop="true" // 点击某一条记录,颜色会显示在最上面,记录上的文字被遮住,所以点击文字不放,文字就看不到
// 设置为false,点击某条记录不放,颜色会在记录的后面,成为背景色,但是记录内容的文字是可见的
android:divider//在列表条目之间显示的drawable或color
android:dividerHeight//用来指定divider的高度
android:entries//构成ListView的数组资源的引用。对于某些固定的资源,这个属性提供了比在程序中添加资源更加简便的方式
android:footerDividersEnabled//当设为false时,ListView将不会在各个footer之间绘制divider.默认为true。
android:headerDividersEnabled//当设为false时,ListView将不会在各个header之间绘制divider.默认为true。 </span>
4.2 继承自AbsListView的XML属性
<span style="font-family:SimSun;font-size:14px;"> 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 列表会自动滑动到底部,无论新条目是否已经准备好显示. </span>
4.3 继承自ViewGroup的XML属性
<span style="font-family:SimSun;font-size:14px;"><span style="white-space:pre"> </span>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保留绘图缓存 </span>
5.常用方法
5.1 add/remove 方法
<span style="font-family:SimSun;font-size:14px;"><span style="white-space:pre"> </span>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 </span>
5.2 响应事件方法
<span style="font-family:SimSun;font-size:14px;"> boolean OnKeyDown(int keyCode,KeyEvent event)//当按下键时响应
boolean OnKeyMultiple(int keyCode,int repeatCount,KeyEvent event)//重复按下键时响应,repeatCount为按下次数
boolean OnKeyUp(int keyCode,KeyEvent event)//当键被释放时响应 </span>
5.3 get方法
<span style="font-family:SimSun;font-size:14px;"> 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 </span>
5.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下方的第一条条目
6.适配器
ListView通过适配器连接显示的数据。要使用ListView,首选要了解适配器,在显示内容时,适配器最方便。
最常见的适配器如下
Adapter | 含义 |
ArrayAdapter<T> | 用来绑定一个数组,支持泛型操作 |
SimpleAdapter | 用来绑定在xml中定义的控件对应的数据 |
SimpleCursorAdapter | 用来绑定游标得到的数据 |
BaseAdapter | 通用的基础适配器 |
6.1 ArrayAdapter
用ArrayAdapter可以实现简单的ListView的数据绑定。默认情况下,ArrayAdapter绑定每个对象的toString值到layout中预先定义的TextView控件上。ArrayAdapter的使用非常简单。
String citys[] = new String[]{"北京", "上海", "天津", "青岛", "济南", "临沂", "天津",
"广州", "深圳", "汕头", "哈尔滨", "大连", "台湾", "日照", "西安", "成都", "沈阳",
"菏泽", "泰安", "郑州", "徐州", "香港", "澳门"};
ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, citys);
listView.setAdapter(adapter);
6.2 SimpleAdapter
很多时候需要在列表中展示一些除了文字以外的东西,比如图片等。这时候可以使用SimpleAdapter。SimpleAdapter的使用也非常简单,同时它的功能也非常强大。可以通过它自定义ListView中的item的内容,比如图片、多选框等.
/**
* @param context 上下文
* @param data 数据源(List<Map>)
* @param resource item显示的布局文件
* @param from item中需要显示的条目(对应Map中的key)
* @param to item中显示内容的空间,与参数三一一对应
*/
SimpleAdapter adapter = new SimpleAdapter(this, listsData, R.layout.item_lists, new String[]{"name", "age", "sex"},
new int[]{R.id.tv_name, R.id.tv_sum, R.id.iv_sex});
lv_simpleAda.setAdapter(adapter);
item布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_name"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="赵四"
android:textSize="18sp"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_sum"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:text="23"
/>
<ImageView
android:id="@+id/iv_sex"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_marginStart="10dp"
android:src="@mipmap/icon_man"/>
</LinearLayout>
</LinearLayout>
List<Map<String, Object>> listsData;
listsData = new ArrayList<>();
Map map;
map = new HashMap();
map.put("name", "风");
map.put("age", 23);
map.put("sex", R.mipmap.icon_man);
listsData.add(map);
6.3 SimpleCursorAdapter
查询数据库,获得Curor数据需要展示时,可以选用SimpleCursorAdapter。
Cursor c =getContentResolver().query(Contacts.People.CONTENT_URI,
null, null, null, null);
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, c,
new String[] {Contacts.People.NAME} ,
new int[] {android.R.id.text1});
listView.setAdapter(adapter);
6.4 BaseAdapter
BaseAdapter作为万能的Adapter,任何数据源都可以通过重写继承于BaseAdapter的类来实现。
在ListView的使用中,有时候还需要在里面加入按钮等控件,实现单独的操作。也就是说,这个ListView不再只是展示数据,也不仅仅是这一行要来处理用户的操作,而是里面的控件要获得用户的焦点。读者可以试试用SimpleAdapter添加一个按钮到ListView的条目中,会发现可以添加,但是却无法获得焦点,点击操作被ListView的Item所覆盖。这时候最方便的方法就是使用灵活的适配器BaseAdapter了。
重写Adapter
private class MyAdapter extends BaseAdapter {
public int getCount() {
return null == listsStu ? 0 : listsStu.size();
}
public Object getItem(int position) {
return listsStu.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
TextView tv_name;
TextView tv_age;
ImageView iv_sex;
Stu stu;
if (null == convertView) {
LayoutInflater inflater = LayoutInflater.from(AtyBaseAdapter.this);
convertView = inflater.inflate(R.layout.item_lists, null);
}
stu = listsStu.get(position);
tv_name = ViewHolder.get(convertView, R.id.tv_name);
tv_age = ViewHolder.get(convertView, R.id.tv_sum);
iv_sex = ViewHolder.get(convertView, R.id.iv_sex);
tv_name.setText(stu.getStu_name());
tv_age.setText(String.valueOf(stu.getStu_age()));
if (0 == stu.getStu_sex()) {
iv_sex.setImageResource(R.mipmap.icon_man);
} else {
iv_sex.setImageResource(R.mipmap.icon_woman);
}
return convertView;
}
}
在Activity中:
<span style="white-space:pre"> </span>MyAdapter mMyAdapter = new MyAdapter();
listView.setAdapter(mMyAdapter);
6.5 android:entries 属性
如果单纯的显示String数组,ListView的android:entries属性,对于某些固定的资源,这个属性提供了比在程序中添加资源更加简便的方式。
XML 定义固定资源:
<string-array name="books">
<item>C语言基础</item>
<item>Java基础</item>
<item>C#基础</item>
<item>C++基础</item>
</string-array>
XML中设置
ListView的
android:entries 属性
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:entries="@array/books">
</ListView>
以上只是简单的总结了在ListView中使用Adapter的几种方式。如果不懂得可查看
listview与adapter用法,Adapter的使用,特别的详细。
7. 常见问题汇总
7.1 设置间隔线高度
设置 android:divider="@color/colorPrimary",必须设置dividerHeight属性。若不设置 dividerHeight,ListView显示时,没有间隔线如果不想显示分割线则只要设置为android:divider="@drawable/@null" 就可以了7.2 隐藏滚动条
android:scrollbars="none"
7.3 addHeaderView(view) 和 addFooterView(view);
当listview需要添加headerview时,可以通过调用listview的addHeaderView(headView, null, false) 方法,该方法还有一个重载方法 addHeaderView(headView);这两个方法的区别是前一个方法可以控制header是否可以被selected,如果不想被selected则将第三个参数设置成false;addHeaderView方法必须放在listview.setadapter前面,给listview添加头部必须在绑定adapter前添加,否则会报错。原因是当我们在调用setAdapter方法时android会判断当前listview是否已经添加header,如果已经添加则会生成一个新的tempadapter,这个新的tempadapter包含我们设置的adapter所有内容以及listview的header和footer。所以当我们在给listview添加了header后在程序中调用listview.getadapter时返回的是tempadapter而不是我们通过setadapter传进去的adapter。如果没有设置adapter则tempadapter与我们自己的adapter是一样的。listview.getadapter().getcount()方法返回值会比我们预期的要大,原因是添加了header。
7.4 ScrollView嵌套ListView
7.4.1.手动计算ListView高度
/**
* 动态设置ListView的高度
* @param listView
*/
public static void setListViewHeightBasedOnChildren(ListView listView) {
if(listView == null) return;
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// pre-condition
return;
}
int totalHeight = 0;
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
}
注意细节:1.Adapter中getView方法返回的View的必须由LinearLayout组成,因为只有LinearLayout才有measure()方法,如果使用其他的布局如RelativeLayout,在调用listItem.measure(0, 0);时就会抛异常,因为除LinearLayout外的其他布局的这个方法就是直接抛异常的.2.使用此方法时,如果每次更改数据,都需要调用此方法,重新计算ListView的高度。
7.4.2 自定义可适应ScrollView的ListView
public class ListViewForScrollView extends ListView {
public ListViewForScrollView(Context context) {
super(context);
}
public ListViewForScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ListViewForScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
/**
* 重写该方法,达到使ListView适应ScrollView的效果
*/
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}
注意:默认显示的首项是ListView,需要手动把ScrollView滚动至最顶端。
sv = (ScrollView) findViewById(R.id.act_solution_4_sv);
sv.smoothScrollTo(0, 0);
ListView使用过程中,碰到的问题,暂时这些。以后若碰到其它会问题,会及时添加进来。如果有哪位碰到了其它的问题,麻烦告知,我统计进来,共同查阅。