androidAdapter应用大全.docx
《androidAdapter应用大全.docx》由会员分享,可在线阅读,更多相关《androidAdapter应用大全.docx(16页珍藏版)》请在冰豆网上搜索。
androidAdapter应用大全
在android开发中列表的使用是十分常见的。
google对列表的封装使列表既有显示传统文本列表的能力,也有加入了诸如选择项、复选项等处理事件的能力。
这里写一些我这几天对这个问题的理解。
在android的api中,List和adapter都被放在了android.widget包内。
包内的具体结构我这里先不展示了,主要侧重列表和adapter。
adapter的作用就是将要在列表内显示的数据和列表本身结合起来。
列表本身只完成显示的作用,其实他就是继承自VIEWGROUP类。
但是他又有一个独特的函数就是setAdapter()就是完成了view和adapter的结合。
adapter如同其本身含义,其实就是一个适配器,他可以对要显示的数据进行统一的封装,主要是将数据变成view提供给list。
我们先来看看adapter的体系:
publicinterfaceAdapter----0层(表示继承体系中的层次)
publicinterfaceExpandableListAdapter---(无所谓层次因为没有其他接口继承实现它)
这是adapter的始祖,其他个性化的adapter均实现它并加入自己的接口。
publicinterfaceListAdapter----1层
publicinterfaceSpinnerAdapter----1层
publicinterfaceWrapperListAdapter----2层(实现ListAdapter)
以上接口层面上的体系已经完了。
可以看出来作为widgetview的桥梁adapter其实只分为2种:
ListAdapter和SpinnerAdapter以及ExpandableListAdapter。
也就是说所有widget也就是基于list和spinne与ExpandableList三种view形式的。
由于在实际使用时,我们需要将数据加入到Adapter,而以接口形式呈现的adapter无法保存数据,于是Adapter就转型为类的模式。
publicabstractclassBaseAdapter----2层(实现了ListAdapter和SpinnerAdapter)
以抽象类的形式出现构造了类型态下的顶层抽象,包容了List和Spinner
publicclassArrayAdapter----3层
publicclassSimpleAdapter---3层
publicclassCursorAdapter----3层(CursorAdapter其后还有子类这里先不探讨)
基本体系有了之后,让我们看看顶层Adapter里有哪些方法(只列举常用的):
abstractObjectgetItem_r(intposition)
abstractintgetCount_r()
abstractlonggetItemId_r(intposition)
abstractintgetItemViewType_r(intposition)
abstractViewgetView_r(intposition,ViewconvertVeiw,ViewGroupparent)
以上是比较重要的方法,ArrayAdapter他们也是重新实现以上方法的。
在实际的开发过程中,往往我们要自己做属于自己的Adapter,以上方法都是需要重新实现的。
这个在android提供的APIdemo例子中可以看到。
androidadapter深刻分析
listview加载adapter过程是这样的.
1 先判断adapter有多少数据项,根据这个数据确定有多少item.
2 确定每个item里加载哪个View.
3 把View里加载要显示的数据.
问提一个一个来解决. 第一个问题:
因为adapter都要关联一个list.有来存储数据.list的项数就是Item的数目. 我们在重载BaseAdapter时候,都要实现这个函数
publicintgetCount(){
returnweatherList.size();
}
哎,这个函数就是确定关联条目的.
第二个问题 哪来的view呢, 当然我们自己创建的.重载BaseAdapter时候你要实现getView()这个函数,就是这个view.
第三个问题,你自己创建的view.加载哪些数据你该知道的.呵呵.
publicclassCustomAdapterActivityextendsListActivity
{
/**Calledwhentheactivityisfirstcreated.*/
@Override
publicvoidonCreate(BundlesavedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ArrayListweatherList=newArrayList();
Weatherw=newWeather("London",17,Weather.OVERCAST);
weatherList.add(w);
w=newWeather("Paris",22,Weather.OVERCAST);
weatherList.add(w);
w=newWeather("Athens",29,Weather.SUNNY);
weatherList.add(w);
w=newWeather("Stockholm",12,Weather.RAIN);
weatherList.add(w);
WeatherAdapterweatherAdapter=newWeatherAdapter(
this,
weatherList);
setListAdapter(weatherAdapter);
}
}
哎,这个大家都很清楚,关键问题是weatherAdapter哪来的呢?
自己创建的啊,如果创建呢?
publicclassWeatherAdapterextendsBaseAdapter{
privateContextcontext;
privateListweatherList; 这就是adapter关联的List,用来存储数据.还记的ArrayList 要往里传参数吗?
传的也是这个类型啊.呵呵
publicWeatherAdapter(Contextcontext,ListweatherList){
this.context=context;
this.weatherList=weatherList;
}
publicintgetCount(){
returnweatherList.size();
}
publicObjectgetItem(intposition){
returnweatherList.get(position);
}
publiclonggetItemId(intposition){
returnposition;
}
publicViewgetView(intposition,ViewconvertView,ViewGroupparent){
Weatherweather=weatherList.get(position);
returnnewWeatherAdapterView(this.context,weather);
}
}
哎,这段告诉了我们,有多少个Item, 可以通过getCount()得到了。
可是View哪来的呢?
当然是getView()这个函数提供.
这个view的获取就多中多样了,我们可以传个LayoutID.通过Inflater出来,也可以自己创建个,只要出来就行.
在这里,我们自己创建个View.这个View.是个VIewGroup.
classWeatherAdapterViewextendsLinearLayout{
publicstaticfinalStringLOG_TAG="WeatherAdapterView";
publicWeatherAdapterView(Contextcontext,
Weatherweather){
super(context);
this.setOrientation(HORIZONTAL);
LinearLayout.LayoutParamscityParams=
newLinearLayout.LayoutParams(100,LayoutParams.WRAP_CONTENT);
cityParams.setMargins(1,1,1,1);
TextViewcityControl=newTextView(context);
cityControl.setText(weather.getCity());
addView(cityControl,cityParams);
LinearLayout.LayoutParamstemperatureParams=
newLinearLayout.LayoutParams(20,LayoutParams.WRAP_CONTENT);
temperatureParams.setMargins(1,1,1,1);
TextViewtemperatureControl=newTextView(context);
temperatureControl.setText(Integer.toString(weather.temperature));
addView(temperatureControl,temperatureParams);
LinearLayout.LayoutParamsskyParams=
newLinearLayout.LayoutParams(25,LayoutParams.WRAP_CONTENT);
ImageViewskyControl=newImageView(context);
Log.d(LOG_TAG,weather.getCity()+"->"+weather.sky);
skyControl.setImageResource(weather.getSkyResource());
addView(skyControl,skyParams);
}
}
首先,来看一下Adapter的体系结构:
一个Adapter的对象扮演一个桥梁的角色。
这个桥梁连接着一个AdapterView和它所包含的数据。
Adapter提供了一个通到数据项的途径。
Adapter还负责为在数据集里的每个数据生项生成一个View。
它有一个重要的方法:
publicabstractViewgetView(intposition,ViewconvertView,ViewGroupparent)。
这个方法被setListAdapter(adapter)间接地调用。
getView方法的作用是得到一个View,这个view显示数据项里指定位置的数据,你可以或者手动创建一个view或者从一个XMLlayout中inflate。
当这个view被inflated,它的父view(如GridView,ListView等)将要使用默认的layout参数,除非你用inflate(int,android.view.ViewGroup,boolean)方法来指定一个根view并防止附着在根上。
下面,分别讲一下它的几个常见的子类:
ListAdapter接口:
继承于Adapter。
ListAdapter是一个ListView和list上的数据之间的桥梁。
数据经常来自于一个Cursor,但这不是必须的。
ListView能显示任何数据,只要它是被一个ListAdapter包装的。
BaseAdapter抽象类:
是一个实现了既能在ListView(实现了ListAdapter接口)和Spinner(实现了Spinner接口)里用的Adapter类的一般基类。
ArrayAdapter类:
一个管理这样的ListView的ListAdapter:
这个ListView被一个数组所支持。
这个数组可装任意对象。
默认状态下,这个类预期能这样:
提供的资源id与一个单独的TextView相关联。
如果你想用一个更复杂的layout,就要用包含了域id的构造函数。
这个域id能够与一个在更大的layout资源里的TextView相关联。
它将被在数组里的每个对象的toString()方法所填满。
你可以添加通常对象的lists或arrays。
重写你对象的toString()方法来决定list里哪一个写有数据的text将被显示。
如果想用一些其它的不同于TextView的view来显示数组(比如ImageViews),或想有一些除了toString()返回值所填在views里的以外的数据,你就要重写getView(int,View,ViewGroup)方法来返回你想要的View类型。
SimpleAdapter类:
一个使静态数据和在XML中定义的Views对应起来的简单adapter。
你可以把list上的数据指定为一个Map范型的ArrayList。
ArrayList里的每一个条目对应于list里的一行。
Maps包含着每一行的数据。
你先要指定一个XML,这个XML定义了用于显示一行的view。
你还要指定一个对应关系,这个对应关系是从Map的keys对应到指定的views。
绑定数据到views发生在两个阶段:
如果一个simpleAdapter.ViewBinder是可用的,那么SetViewValue(android.view.View,Object,String)要被调用。
如果返回true,那么绑定发生了。
如果返回false,那么如下views将被按顺序地尝试:
~实现了Checkable的View(如CheckBox),预期的绑定值是boolen
~TextView,预期的绑定值是String,并且SetViewText方法被调用
~ImageView,预期的绑定值是一个资源的id或String。
并且SetViewImage方法被调用
如果没有合适的绑定被发现,一个IllegalStateException被抛出。
下面,是一个SimpleAdapter的例子:
xmlns:
android="
android:
orientation="vertical"
android:
layout_width="fill_parent"
android:
layout_height="fill_parent">
android:
layout_width="fill_parent"
android:
layout_height="fill_parent"
android:
id="@+id/MyListView">
xmlns:
android="
android:
id="@+id/widget0"
android:
layout_width="fill_parent"
android:
layout_height="fill_parent">
android:
id="@+id/ItemImage"
android:
layout_width="wrap_content"
android:
layout_height="wrap_content">
android:
id="@+id/ItemTitle"
android:
layout_width="fill_parent"
android:
layout_height="wrap_content"
android:
text="TextView"
android:
layout_x="50px"
android:
textSize="15pt">
android:
id="@+id/ItemText"
android:
layout_width="fill_parent"
android:
layout_height="wrap_content"
android:
text="TextView"
android:
layout_x="50px"
android:
layout_y="40px">
android:
id="@+id/ItemCheck"
android:
layout_width="wrap_content"
android:
layout_height="wrap_content"
android:
layout_x="270px">
publicclassTestUIListextendsActivity{
publicvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ListViewlist=(ListView)findViewById(R.id.MyListView);
ArrayList>lstImageItem=newArrayList>();
String[]str1={"rowone","rowtwo","rowthree","rowfour"};
String[]str2={"第一行","第二行","第三行","第四行"};
for(inti=0;iHashMapmap=newHashMap();
map.put("ItemImage",R.drawable.icon);
map.put("ItemTitle",str1[i]);
map.put("ItemText",str2[i]);
lstImageItem.add(map);
}
SimpleAdaptersaImageItems=newSimpleAdapter(this,
lstImageItem,
R.layout.simple_list_item_2,
newString[]{"ItemImage","ItemTitle","ItemText"},
newint[]{R.id.ItemImage,R.id.ItemTitle,R.id.ItemText});
list.setAdapter(saImageItems);
}
}
如果你的ListView的每一行想实现被点击后有响应事件。
最省事发的方法是继承一个ListActivity。
ListActivity是一个这样的Activity:
这个Activity能通过绑定到一个像array或cursor这样的数据源来显示一些items的list,并且当用户选了一个item时,能够暴露事件句柄。
ListActivity拥有一个ListView对象。
这个ListView对象能够被绑定到不同的数据源,特别是一个数组或者一个拥有查询结果的Cursor。
ListActivity有三种用法,分别是Binding,ScreenLayout和RowLayout。
下面,仅讨论一下ScreenLayout:
ListActivity有一个默认的layout。
这个layout是由一个在屏幕中央的、单独的、全屏的list构成。
然而,如果你想的话,你可以通过在onCreate()里调用setContentView()方法来设置你自己的viewlayout的方式制定屏幕layout。
要这样做,你自己的view必须包含一个id为“@android:
id/android:
list”(或者在代码中有list对象)。
随意地,当你制定这个view是空的时,你能够包含任何类型的view对象来显示。
这个“空list”通知者必须有一个id“android:
empty”。
注意,最后一定要调用setListAdapter(adapter)方法来把通过Adapter绑定了数据的这个List显示出来。
setListAdap