Android用户界面 UI组件--AdapterView及其子类(一) ListView及各种Adapter详解
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
②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"
③保留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
.
Android用户界面 UI组件--AdapterView及其子类(一) ListView及各种Adapter详解的更多相关文章
- Android用户界面 UI组件--AdapterView及其子类(二) AdapterViewAnimator及其子类
AdapterViewAnimator:当在视图间切换时会显示动画. android:animateFirstView 定义ViewAnimation首次显示时是否对当前视图应用动画. android ...
- Android用户界面UI组件--AdapterView及其子类(五) Spinner和SpinnerAdapter
Spinner就是下拉框组件,可以自定义下拉布局样式,可以使用ArrayAdapter以及SpinnerAdapter适配 在Adapter中实现SpinnerAdapter,继承BaseAdapte ...
- Android用户界面UI组件--AdapterView及其子类(四) GridView
GridView常用的XML属性: android:columnWidth 设置列的宽度. android:horizontalSpacing 两列之间的间距. android:numColum ...
- Android用户界面UI组件--AdapterView及其子类(三) ExpandableListView
ExpandableListView: List中的每一项可以展开收缩. 一种伸缩式的ListView. android:cacheColorHint="#00000000" 这个 ...
- Android用户界面 UI组件--TextView及其子类(二) Button,selector选择器,sharp属性
1.XML文件中的OnClick 属性可以指定在Activity中处理点击事件的方法,Activity中必须定义该属性指定的值作为方法的名字且有一个View类型的参数,表示此物件被点击. 2.使用se ...
- Android用户界面 UI组件--TextView及其子类(三) EditView以及各种Span文字样式讲解
EditView和TextView的用法差不多,只是文字可编辑 小技巧: 设置EditText隐藏键盘 setInputType(0); 设置EditText不被输入法遮盖 getWindow() ...
- Android用户界面 UI组件--TextView及其子类(一) TextView
1.TextView android:autoLink设置是否当文本为URL链接/email/电话号码/map时,文本显示为可点击的链接.可选值(none /web/email/phone/map/a ...
- Android用户界面 UI组件--TextView及其子类(五) DigitalClock,AnalogClock,RadioButton,CheckBox,ToggleButton汇总
DigitalClock和AnalogClock两个时钟类 可以为DigitalClock设置背景图片,自定义时针,秒针,分针的样式 例子: <?xml version="1.0&qu ...
- Android用户界面 UI组件--ImageView及其子类ImageButton,QuickContactBadge附带Draw9Patch工具说明
1.ImageView 常用属性: android:src 设置可绘制对象作为 ImageView 显示的内容 android:cropToPadding 如果设置为true,图片裁剪到保留该Imag ...
随机推荐
- 在网页中添加分享到微信、QQ、微博
参考地址:http://www.bshare.cn/help/installAction 在上面的地址中: 1.可选择分享到的位置,如QQ.微信.微博等 2.按钮的样式.悬浮或者以横幅的方式自己找位置 ...
- DNS加速之“智能DNS”跟“双线加速”、“CDN加速”的区别
“智能DNS”跟“双线加速”.“CDN加速”的区别相信,很大部分IDC用户可能还没弄清楚状况,有人觉得智能DNS跟双线加速.CDN加速是类似的技术.其实不然,它们在工作方式上有着本质的区别,但它们又可 ...
- js_BOM_05
1.下拉级联 |-select的API |-如何获得选中的option? |-如何创建option? |-如何将option添加到select? |-如何移 ...
- SQL Server2008R无法登录的解决方案(系统文件损坏)1814 18456....不看别后悔,有用请点赞
废话 早上一开电脑,黑屏幕跑一些修复系统的代码....进入系统后,sql server连接不上 正文 原因:sql server的服务自动关闭了,并且启动失败 windows日志信息:传递给数据库 ' ...
- JavaMail组件实现邮件功能
实现邮件收发功能需要3个jar包: 1.JavaMail组件保内的mail.jar和smtp.jar包 2.JAF组件包里的activition.jar. 复制到WebRoot/WEB-INF/lib ...
- ACM——回文
回文回文! 时间限制(普通/Java):1000MS/3000MS 运行内存限制:65536KByte总提交:967 测试通过:338 描述 回文是一种有趣的现 ...
- (转) sphinx 高亮显示搜索词
http://hi.baidu.com/tewuapple/item/7a7bc34adbda24a8df2a9fe5 (转)
- linux/win7下安装websphere application server
说明: 1.参考网址:http://www.ibm.com/developerworks/cn/aix/library/au-wasonlinux/ 2.在ibm官网上下载websphere appl ...
- APUE学习笔记-一些准备
从开始看APUE已经有快一个星期了,由于正好赶上这几天清明节放假,难得有了三天空闲假期可以不受打扰的学习APUE,现在已经看完前六章了,里面的大部分例程也都亲自编写,调试过了.但总觉得这样学过就忘,因 ...
- ECMAScript位操作符
在ECMAScript中,有少数的几个操作符可以对二进制位进行直接操作,这几个操作符本身直接对二进制进行操作,所有它们的本身是非常效率的,学习这一段有助于以后的优化以及理解. ECMAScript中采 ...