ListView就是列表组件,一般通过继承ListActivity使用系统提供的ListView.

所有的AdapterView组件都需要有一个对应的Adapter作为适配器来显示列表中元素的布局方式

见思维导图

AbsListView的常用XML属性:

android:choiceMode

设置ListView的选择行为 none:不显示任何选中项 singleChoice:允许单选  multipleChoice:允许多选

android:drawSelectorOnTop

设置为true,则选中的列表项会显示在上面

android:fastScrollEnabled

是否允许快速滚动

android:listSelector

指定被选中的列表项上绘制的Drawable

android:scrollingCache

是否使用绘制缓存

android:smoothScrollBar

如果设置为false,则不在header View之后绘制分隔条

android:stackFromBottom

设置是否从底端开始排列列表项

android:textFilterEnabled

设置是否对列表项进行过滤.当对应的Adapter实现了Filter接口时该属性才会起作用

android:transcriptMode

设置该组件的滚动模式。disable:关闭滚动,这是默认值   normal:当listView收到数据改变通知,且最后一个列表项可见时,将会自动滚动到底端。 alwaysScoll:该listView总会自动滚动到底端

android:divider

设置List列表项的分隔条(既可用颜色分隔,也可用Drawable分隔)

android:dividerHeight

分隔条高度

android:entries

指定一个数组资源,生成一个ListView

android:footerDividersEnabled

设置为false,则不在footer View之前绘制分隔条

android:headerDividersEnabled

设置为false,则不在header View之后绘制分隔条

ArrayAdapter: 数组或集合的适配器。

例:
private final String[] mous = {
        "郭嘉",
        "荀攸",
        "荀彧",
        "程昱",
        "戏志才",
        "徐庶"
};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,mous);

也可以在XML文件中用android:entries属性指定绑定的数组资源文件
资源文件存放在value文件夹下
如:
android:entries="@array/book"

<string-array name="book" >
        <item >1</item>
        <item >2</item>
        <item >3</item>
        <item >3</item>
</string-array>

例子

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" > <ListView
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="match_parent"
/> </LinearLayout>
package com.light.android.study;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView; public class MainActivity extends Activity { private final String[] mous = {
"郭嘉",
"荀攸",
"荀彧",
"程昱",
"戏志才",
"徐庶"
};
private ListView lv; @Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
initAdapter();
} private void init(){
lv = (ListView) findViewById(R.id.lv);
} private void initAdapter(){
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,mous);
lv.setAdapter(adapter);
} }

效果:

SimpleAdapter:简单的Adapter实现

SimpleAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)
第一个参数是Context对象
第二个参数是保存有每一行数据的Map构成的List对象,也就是说,每一行数据里的每一个属性都由它的名字和它的值构成一个键值对,多个属性有多个键值对,每一行的多个键值对构成这一行的一个Map对象,这一行的Map对象对应到这个List中.
第三个参数布局文件Id
第四个参数Map对象中的多个键值对的key值
第五个参数布局文件中用来显示内容的组件ID

SimpleAdapter绑定数据到视图分两个阶段
1.首先,如果设置了SimpleAdapter.ViewBinder,那么这个设置的ViewBinder的setViewValue(android.view.View, Object, String)将被调用.如果setViewValue的返回值是true,则表示绑定已经完成,将不再调用系统默认的绑定实现.
2.如果返回值为false,视图将按以下顺序绑定数据:
•如果View实现了Checkable(例如CheckBox),期望绑定值是一个布尔类型.
•TextView.期望绑定值是一个字符串类型,通过调用setViewText(TextView, String)绑定.
•ImageView,期望绑定值是一个资源id或者一个字符串,通过调用setViewImage(ImageView, int) 或 setViewImage(ImageView, String)绑定数据.
如果没有一个合适的绑定发生将会抛出IllegalStateException.

例子:

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" > <!-- 定义一个List --> <ListView
android:id="@+id/mylist"
android:layout_width="fill_parent"
android:layout_height="wrap_content" /> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" > <!-- 定义一个ImageView,用于作为列表项的一部分。 --> <ImageView
android:id="@+id/header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
tools:ignore="ContentDescription" /> <!-- 定义一个TextView,用于作为列表项的一部分。 --> <TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingLeft="10dp"
android:textSize="16sp" /> </LinearLayout>
package com.light.android.study;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;
import android.widget.SimpleAdapter; public class MainActivity extends Activity {
private String[] names = new String[] { "杜甫", "弄玉", "清照", "李白" };
private int[] imageIds = new int[] { R.drawable.tiger, R.drawable.nongyu,
R.drawable.qingzhao, R.drawable.libai }; @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
List<Map<String, Object>> listItems = new ArrayList<Map<String, Object>>();
for (int i = 0; i < names.length; i++) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("header", imageIds[i]);
map.put("personName", names[i]);
listItems.add(map);
} //創建SimpleAdapter
SimpleAdapter simpleAdapter = new SimpleAdapter(this, listItems,
R.layout.list_item_layout, new String[] { "personName", "header" },
new int[] { R.id.name, R.id.header }); ListView list = (ListView) findViewById(R.id.mylist);
list.setAdapter(simpleAdapter);
}
}

效果:

CursorAdapter:

Cursor型集合的适配器,与数据库连接的桥梁
其中游标携带的结果集中必须有列名为“_id”的列,否则这个类无法工作.
getView()
每一项显示的设置
bindView()
把数据和已经生成的View绑定在一起
newView()
新建一个View
CursorAdapter中源码 getView的实现
public View getView(int position, View convertView, ViewGroup parent) {
 View v;
 if (convertView == null) {
   v = newView(mContext, mCursor, parent);
 } else {
   v = convertView;
 }
 bindView(v, mContext, mCursor);
 return v;
}
getView首先使用已经存在的View,如果没有就调用newView 产生一个,然后把数据bind上去

我们一般使用其子类SimpleCursorAdapter来实现查询出来的数据List的Adapter

SimpleCursorAdapter(Context context,int layout,Cursor c,String[] from,int[] to,int flags)
context:当前Context对象
layout:布局文件Id
c:集合
from:需要绑定的集合中的列的名字
to:显示项目的View的id集合,在layout布局文件中定义
flags:用来判断适配器的行为标志
建议使用CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER
适配器会在游标上注册一个内容观测器,当通知到达时会调用 onContentChanged() 方法.使用该标志位时要注意:在注册观察器时需要先解除当前游标与适配器的关联,防止发生泄漏.
Android 3.0引入了CursorLoader实现异步加载数据,为了避免同步查询数据库时阻塞UI线程的问题。所以一般先将SimpleCursorAdapter中的Cursor对象放空,然后用CursorLoader对象加载数据,再放入适配器。
例子:

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" > <ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
/> </LinearLayout>

Item布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="64dip"
android:orientation="horizontal"
android:gravity="center_vertical"
android:paddingLeft="8dip"> <TextView android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:gravity="center_vertical"
android:singleLine="true"
android:fadingEdge="horizontal"
android:fadingEdgeLength="3dip"
android:ellipsize="marquee"
/>
</LinearLayout>
package com.light.android.study;

import android.app.ListActivity;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.Context;
import android.content.CursorLoader;
import android.content.Loader;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.widget.SimpleCursorAdapter; //實現接口作為CursorLoader
public class MainActivity extends ListActivity implements LoaderCallbacks<Cursor> {
private SimpleCursorAdapter mAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); // Create an empty adapter we will use to display the loaded data.
mAdapter = new SimpleCursorAdapter(MainActivity.this,
R.layout.contacts_list_item, null,
new String[] { ContactsContract.Contacts.DISPLAY_NAME },
new int[] { android.R.id.text1 },
0); getListView().setAdapter(mAdapter); //初始化Loader
//第一個參數 為這個Loader對象指定唯一的标识ID,第二个可选参数,用来支持Loader的构造方法,
//第三个参数是LoaderCallbacks接口类型
getLoaderManager().initLoader(0, null, this);
} public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// 去数据库读取数据等要消耗大量时间的操作放在
// 自定义 CursorLoader 的 onLoadInBackground
return new MyCursorLoader(getApplicationContext());
} public void onLoadFinished(Loader<Cursor> arg0, Cursor cursor) {
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
mAdapter.swapCursor(cursor);
} public void onLoaderReset(Loader<Cursor> arg0) {
// This is called when the last Cursor provided to onLoadFinished()
// above is about to be closed. We need to make sure we are no
// longer using it.
mAdapter.swapCursor(null);
} public static class MyCursorLoader extends CursorLoader {
String[] mContactProjection = { ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME };
private Context mContext; public MyCursorLoader(Context context) {
super(context);
mContext = context;
} /**
* 4.自定义 CursorLoader 的 onLoadInBackground
* 会返回一个Cursor,这里给SimpleCursorAdapter用
* 来填充数据。查询数据等操作放在这里执行
*/
@Override
protected Cursor onLoadInBackground() {
Cursor cursor = mContext.getContentResolver().query(
ContactsContract.Contacts.CONTENT_URI, mContactProjection,
null, null, null);
return cursor;
}
}
}

效果:

最后看下BaseAdapter

经常需要覆写的方法

boolean isEnabled (int
position):

如果列表的一项item是separator(充当分隔项目,跟其他item项一样,也可以不一样,但是无法进行点击),返回true,也就是可以点击,并接收响应事件。如果此时position处的item是separator的话,返回false,也就无法响应点击或触摸事件,此项目是不可以点击的,表现形式为点了没任何反应,可以充当一个列表中的分隔,当然可以自定义这个分隔项的布局。

abstract Object getItem(int position)
得到位于position位置的项

public int getViewTypeCount() 

返回共有多少个不同的布局

abstract int getCount()
得到项目总数
abstract long getItemId(int position)
得到位于position位置的项的Id
public int getItemViewType(int position)
以int数值型返回itemView的类型。一般普通列表的item都是一样的布局,也就是说这个列表只有一种类型,但是很多时候我们需要列表显示不同的item,比如有的列表有普通item和separator两种类型,item用于响应用户点击事件,separator用于分隔item,不可以点击,这样这个列表就有了两种类型,重载这个方法,如果当前位置是item,我们可以返回1,如果是separator我们可以返回2,以此类推。
abstract View getView(int position,View convertVeiw,ViewGroup parent)
每一项显示的设置
在getView方法中需要缓存加载View优化ListView

官方建议使用ViewHolder,其实就是单例
例:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_item_icon_text, null);
holder = new ViewHolder();
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
holder.text = (TextView) convertView.findViewById(R.id.text);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.icon.setImageResource(R.drawable.icon);
holder.text.setText(mData[position]);
return convertView;
}
static class ViewHolder {
ImageView icon;
TextView text;
}

知识点

①解决ListView滑动过程中背景颜色变黑的问题

android:cacheColorHint="#00000000"// setting transparent color

http://stackoverflow.com/questions/2833057/background-listview-becomes-black-when-scrolling/2833103#2833103

②ListView变圆角显示

定义一个shape:res/drawable/customshape.xml

<?xml version="1.0" encoding="UTF-8"?><shapexmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"><gradientandroid:startColor="#SomeGradientBeginColor"android:endColor="#SomeGradientEndColor"android:angle="270"/><cornersandroid:bottomRightRadius="7dp"android:bottomLeftRadius="7dp"android:topLeftRadius="7dp"android:topRightRadius="7dp"/></shape>

然后在XML中

android:background="@drawable/customshape"

http://stackoverflow.com/questions/1683185/how-do-i-create-a-listview-with-rounded-corners-in-android/1683195#1683195

③保留ListView上次滑动的位置

// save index and top positionint index = mList.getFirstVisiblePosition();View v = mList.getChildAt(0);int top =(v ==null)?0: v.getTop();// ...// restore index and position
mList.setSelectionFromTop(index, top);

说明:

ListView.getFirstVisiblePosition() returns the top visible list item. But this item may be partially scrolled out of view, and if you want to restore the exact scroll position of the list you need to get this offset. So ListView.getChildAt(0) returns the View for the top list item, and then View.getTop() returns its relative offset from the top of the ListView. Then, to restore the ListView's scroll position, we call ListView.setSelectionFromTop() with the index of the item we want and an offset to position its top edge from the top of the ListView.

http://stackoverflow.com/questions/3014089/maintain-save-restore-scroll-position-when-returning-to-a-listview

Android用户界面 UI组件--AdapterView及其子类(一) ListView及各种Adapter详解的更多相关文章

  1. Android用户界面 UI组件--AdapterView及其子类(二) AdapterViewAnimator及其子类

    AdapterViewAnimator:当在视图间切换时会显示动画. android:animateFirstView 定义ViewAnimation首次显示时是否对当前视图应用动画. android ...

  2. Android用户界面UI组件--AdapterView及其子类(五) Spinner和SpinnerAdapter

    Spinner就是下拉框组件,可以自定义下拉布局样式,可以使用ArrayAdapter以及SpinnerAdapter适配 在Adapter中实现SpinnerAdapter,继承BaseAdapte ...

  3. Android用户界面UI组件--AdapterView及其子类(四) GridView

    GridView常用的XML属性: android:columnWidth  设置列的宽度. android:horizontalSpacing  两列之间的间距.  android:numColum ...

  4. Android用户界面UI组件--AdapterView及其子类(三) ExpandableListView

    ExpandableListView: List中的每一项可以展开收缩. 一种伸缩式的ListView. android:cacheColorHint="#00000000" 这个 ...

  5. Android用户界面 UI组件--TextView及其子类(二) Button,selector选择器,sharp属性

    1.XML文件中的OnClick 属性可以指定在Activity中处理点击事件的方法,Activity中必须定义该属性指定的值作为方法的名字且有一个View类型的参数,表示此物件被点击. 2.使用se ...

  6. Android用户界面 UI组件--TextView及其子类(三) EditView以及各种Span文字样式讲解

    EditView和TextView的用法差不多,只是文字可编辑 小技巧: 设置EditText隐藏键盘  setInputType(0); 设置EditText不被输入法遮盖  getWindow() ...

  7. Android用户界面 UI组件--TextView及其子类(一) TextView

    1.TextView android:autoLink设置是否当文本为URL链接/email/电话号码/map时,文本显示为可点击的链接.可选值(none /web/email/phone/map/a ...

  8. Android用户界面 UI组件--TextView及其子类(五) DigitalClock,AnalogClock,RadioButton,CheckBox,ToggleButton汇总

    DigitalClock和AnalogClock两个时钟类 可以为DigitalClock设置背景图片,自定义时针,秒针,分针的样式 例子: <?xml version="1.0&qu ...

  9. Android用户界面 UI组件--ImageView及其子类ImageButton,QuickContactBadge附带Draw9Patch工具说明

    1.ImageView 常用属性: android:src 设置可绘制对象作为 ImageView 显示的内容 android:cropToPadding 如果设置为true,图片裁剪到保留该Imag ...

随机推荐

  1. Linux云主机安装JDK,配置hadoop的详细方式

    云主机我使用的是青云的,还有好多其他品牌,比如阿里云 unitedstack 等等. 注册完青云后,会有试用券发到账户,可以利用此券试用其服务. 1 首先创建好一个主机,按照提示选择好系统,创建好一个 ...

  2. EF6调用存储过程,返回多个结果集处理

    链接:http://www.codeproject.com/Articles/675933/Returning-Multiple-Result-Sets-from-an-Entity-Fram 案例: ...

  3. MVC小系列(十三)【全局异常处理与异常日志】

    在MVC网站的global.asax中的Application_Start方法里,有这样一段代码 protected void Application_Start() { //它的主要作用是将全局过滤 ...

  4. Solr4.8.1与Tomcat7整合

    Solr4.8.1和Tomcat7都可以到官方网站去下载,我这里就不多说了,如下图. 这里我们首先解压Solr-4.8.1.zip,再解压Tomcat,解压后,再在当前文件夹下建2个文件夹,一个用来放 ...

  5. CentOS 7 安装 Apache PHP MariaDB

    准备篇: 一.配置防火墙,开启80端口.3306端口 CentOS 7 默认使用的是firewall作为防火墙,这里改为iptables防火墙. 1.关闭firewall: systemctl sto ...

  6. 第17条:实现description方法

    自定义类需要自己覆写description方法,否则打印信息时就会调用NSObject类所实现的默认方法.(如果不覆写,只会输出类名和对象的内存地址的信息,这只有在判断两个指针是否指向同一对象时才有用 ...

  7. 关于Debug下的Log打印问题

    在项目中为了调试经常会用到Log打印,比如打印当前方法__func__, 对象,地址等等,所以项目最后每次运行调试控制台满满的都是打印日志,到release发布的时候,显然不太合适,这里其实可以用一个 ...

  8. iOS 添加占位符

    添加占位符: 首先占位符的大小要比textView 的大小要小一些 1.添加一个取消键盘的通知 2.添加一个代理事件 1. // removeKeyBoard 添加通知收回键盘 [[NSNotific ...

  9. python+sqlite3

    一个小例子, # -*- coding:utf-8 -*- ''' Created on 2015年10月8日 (1.1)Python 2.7 Tutorial Pt 12 SQLite - http ...

  10. 2015 Multi-University Training Contest 1 题解&&总结

    ---------- HDU 5288 OO’s Sequence 题意 给定一个数列(长度<$10^5$),求有多少区间[l,r],且区间内有多少数,满足区间内其它数不是他的约数. 数的范围$ ...