您的位置:首页 > 移动开发 > Android开发

Using lists in Android [带翻译]

2015-02-08 13:27 399 查看

UsinglistsinAndroid(ListView)–Tutorial

原文地址:http://www.vogella.com/tutorials/AndroidListView/article.html申明:本译文参考谷歌和原文协作翻译,有很小一部分是意译方便理解。如有错误请联系(邮箱:lijunhuayc@sina.comQQ:190951132添加请表明是本文读者)更正。

拉尔斯·沃格尔

Version4.6Copyright©2010,2011,2012,2013,2014vogellaGmbh2014年11月20日AndroidListViewListActivityListFragment的使用本教程介绍了如何结合Activitys和Fragments使用ListView的。本教程是基于Eclipse4.4,Java的1.7和Android5.0。目录1.Android和Lists1.1。在Android中使用Lists1.2。Viewsforhandlinglists1.3。lists中可能的输入类型1.4。适配器1.5。过滤和排序1.6。adapter中的数据更新1.7。listener(监听)2.默认adapter2.1。平台默认adapter2.2。使用ArrayAdapter2.3。使用ArrayAdapter的ListView示例3.自定义实现Adapter3.1。开发自定义adapter3.2。为list准备item布局3.3。自定义adapter示例3.4。更新adapter中的数据模型4.ListActivity和ListFragment4.1。使用ListView的默认容器4.2。ListActivity和自定义布局4.3。空list用作占位5.练习:使用ListView和ListActivity6.运动:给ListActivity添加自己的布局7.教程:实现自己的adapter8.ListViews性能篇8.1。motivation(翻译成“动机”?^_^)8.2。耗时操作8.3。避免布局臃肿和对象的创建8.4。ViewHolder模式8.5。示例9.保存selectionofaview10.ListViews中的上下文actionmode11.执行撤销操作11.1。当你想要提供一个撤消操作?11.2。示例12.性能优化13教程:如何在ListView中显示两个item14.ListView多选操作14.1。数据模型和ListView交互14.2。教程:领域模型和行的交互15.实现可扩展开的ListView15.1。ExpandableListView15.2。ExpandableListView示例16.教程:其他16.1。为item添加longclick监听器16.2。header和footer17.SimpleCursorAdapter18.其他开源库19.关于本网站19.1。捐赠支持免费教程19.2。提问和讨论19.3。授权本教程及其代码20.链接和文学20.1。源代码20.2。ListView的资源20.3。vogella资源

1.AndroidandLists

1.1.UsinglistsinAndroid

Thedisplayofelementsinalistisaverycommonpatterninmobileapplications.Theuserseesalistofitemsandcanscrollthroughthem.Suchanactivityisdepictedinthefollowingpicture.在移动应用中以非常普通的模式显示list中的item。用户可以滚动他们看到的list。如下图。Typicallytheuserinteractswiththelistviatheactionbar,forexample,viaarefreshbutton.Individuallistitemscanbeselected.Thisselectioncanupdatetheactionbarorcantriggeradetailedscreenfortheselection.Thefollowinggraphicsketchesthat.Ontheselectionofalistitemanotheractivityisstarted.通常用户通过操作栏和list交互,比如,按下一个刷新按钮。个别item可被选中,这种选中可以更新操作栏或者打开选中项的详细页。下图展示了选中item打开另一个activity

1.2.Viewsforhandlinglists

Androidprovidesthe
ListView
andthe
ExpandableListView
classeswhichiscapableofdisplayingascrollablelistofitems.The
ExpandableListView
classsupportsagroupingofitems.Android提供了ListView和ExpandableListView能够显示和滚动lists的item。ExpandableListView类支持的item的分组。

1.3。对于列出了可能的输入类型

Theinputtothelist(itemsinthelist)canbearbitraryJavaobjects.Theadapterextractsthecorrectdatafromthedataobjectandassignsthisdatatotheviewsintherowofthe
ListView
.Theseitemsaretypicallycalledthedatamodelofthelist.Anadaptercanreceivedataasinput.List的item可以显示任意的Java对象。adatper从数据对象中提取正确的数据,并显示到list的item中的views中。这些items通常被称为列表的数据模型。适配器可以接收数据作为输入。

1.4。适配器

Anadaptermanagesthedatamodelandadaptsittotheindividualentriesinthewidget.Anadapterextendsthe
BaseAdapter
class.Everylineinthewidgetdisplayingthedataconsistsofalayoutwhichcanbeascomplexasyouwant.Atypicallineinalisthasanimageontheleftsideandtwotextlinesinthemiddleasdepictedinthefollowinggraphic.适配器管理数据模型,将数据放入widget中。适配器继承自BaseAdapter类。显示数据的widget中可以使用任意只要你想要的复杂布局。在一个列表中一个典型的线对的左侧和在如以下图形所示的中间两个文本行图像。Alayoutfileforasuchalinemightlooklikethefollowing.对于这样的布局文件就像下面这样:<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="?android:attr/listPreferredItemHeight" android:padding="6dip"> <ImageView android:id="@+id/icon" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_alignParentBottom="true" android:layout_alignParentTop="true" android:layout_marginRight="6dip" android:contentDescription="TODO" android:src="@drawable/ic_launcher"/> <TextView android:id="@+id/secondLine" android:layout_width="fill_parent" android:layout_height="26dip" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_toRightOf="@id/icon" android:ellipsize="marquee" android:singleLine="true" android:text="Description" android:textSize="12sp"/> <TextView android:id="@+id/firstLine" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_above="@id/secondLine" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:layout_alignWithParentIfMissing="true" android:layout_toRightOf="@id/icon" android:gravity="center_vertical" android:text="Exampleapplication" android:textSize="16sp"/> </RelativeLayout>Theadapterwouldinflatethelayoutforeachrowinits
getView()
methodandassignthedatatotheindividualviewsintherow.Theadapterisassignedtothe
ListView
viathe
setAdapter
methodonthe
ListView
object.TipAdaptersarenotonlyusedbyListView,butalsobyotherviewswhichextendAdapterViewas,forexample,Spinner,GridView,GalleryandStackView.适配器不仅仅适用于ListView,也可用于其他继承了AdapterView的View,比如Spinner、GridView、Gallery、StackView等。

1.5.Filteringandsorting

Filteringandsortingofthedataishandledbytheadapter.Youneedtoimplementthelogicinyourcustomadapterimplementation.数据的过滤和排序由适配器处理。你只需要实现自定义适配器的逻辑。

1.6.Dataupdatesintheadapter

The
notifyDataSetChanged()
methodontheadapteriscalledifthedatahaschangedorifnewdataisavailable.The
notifyDataSetInvalidated()
methodiscalledifthedataisnotavailableanymore.如果数据已经改变或者有新的数据可用,适配器应该调用
notifyDataSetChanged()
如果数据不再可用,应当调用notifyDataSetInvalidated()方法

1.7.Listener

Toreacttoselectionsinthelist,setan
OnItemClickListener
toyour
ListView
.为item设置点击OnItemClickListenerlistView.setOnItemClickListener(newOnItemClickListener(){ @Override publicvoidonItemClick(AdapterView<?>parent,Viewview, intposition,longid){ Toast.makeText(getApplicationContext(), "ClickListItemNumber"+position,Toast.LENGTH_LONG) .show(); } });

2.Defaultadapter

2.1.Defaultplatformadapter

Androidprovidesdefaultadapterimplementations;themostimportantare
ArrayAdapter
and
CursorAdapter
.
ArrayAdapter
canhandledatabasedon
Arrays
or
java.util.List
.
SimpleCursorAdapter
canhandledatabaserelateddata.Android提供了默认的适配器的实现;最重要的是
ArrayAdapter
CursorAdapter
ArrayAdapter
可以处理基于
Arrays
java.util.List
的数据。
SimpleCursorAdapter
可以处理数据库的相关数据。

2.2.UsingArrayAdapter

The
ArrayAdapter
classcanhandlealistorarrayofJavaobjectsasinput.EveryJavaobjectismappedtoonerow.Bydefault,itmapsthe
toString()
methodoftheobjecttoaviewintherowlayout.YoucandefinetheIDoftheviewintheconstructorofthe
ArrayAdapter
otherwisethe
android.R.id.text1
IDisusedasdefault.The
ArrayAdapter
classallowstoremoveallelementsinitsunderlyingdatastructurewiththe
clear()
methodcall.Youcanthenaddnewelementsviathe
add()
methodora
Collection
viathe
addAll()
method.Youcanalsodirectlymodifytheunderlyingdatastructureandcallthe
notifyDataSetChanged()
methodontheadaptertonotifyitaboutthechangesindata.WarningIfyouwanttochangethedatainyouradapter,theunderlyingdatastructuremustsupportthisoperation.Thisis,forexample,thecasefortheArrayListclass,butnotforarrays.

ArrayAdapter
类可以处理Java对象作为输入列表或数组。每个Java对象映射到一行。默认情况下,它映射
toString()
对象的方法,在该行布局视图。您可以定义在的构造函数的视图的ID
ArrayAdapter
否则
android.R.id.text1
ID被用作默认。在
ArrayAdapter
类可删除其底层数据结构中的所有元素与
clear()
方法调用。然后,您可以通过添加新元素
add()
方法或
Collection
通过
addAll()
方法。您也可以直接修改底层的数据结构,并调用
notifyDataSetChanged()
的适配器上的方法,通知它有关的变化数据。警告如果你想改变你的适配器中的数据,底层数据结构必须支持此操作。这是,例如,对于该情况下ArrayList类,但不为阵列。

2.3.ListViewexamplewithArrayAdapter

Thefollowinglistingshowsalayoutfilecalled
activity_listviewexampleactivity.xml
whichincludesa
ListView
.<ListViewxmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/listview" android:layout_width="wrap_content" android:layout_height="wrap_content"/>Thefollowingexampleshowstheusageofthe
ListView
viewinanactivity.ItusesadefaultlayoutfromtheAndroidplatformfortherowlayout.Italsodemonstratestheremovaloflistitemsandusesanimationsfortheremoval.

packagecom.vogella.android.listview.withanimation; publicclassListViewExampleActivityextendsActivity{ @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_listviewexampleactivity); finalListViewlistview=(ListView)findViewById(R.id.listview); String[]values=newString[]{"Android","iPhone","WindowsMobile", "Blackberry","WebOS","Ubuntu","Windows7","MaxOSX", "Linux","OS/2","Ubuntu","Windows7","MaxOSX","Linux", "OS/2","Ubuntu","Windows7","MaxOSX","Linux","OS/2", "Android","iPhone","WindowsMobile"}; finalArrayList<String>list=newArrayList<String>(); for(inti=0;i<values.length;++i){ list.add(values[i]); } finalStableArrayAdapteradapter=newStableArrayAdapter(this, android.R.layout.simple_list_item_1,list); listview.setAdapter(adapter); listview.setOnItemClickListener(newAdapterView.OnItemClickListener(){ @Override publicvoidonItemClick(AdapterView<?>parent,finalViewview, intposition,longid){ finalStringitem=(String)parent.getItemAtPosition(position); view.animate().setDuration(2000).alpha(0) .withEndAction(newRunnable(){ @Override publicvoidrun(){ list.remove(item); adapter.notifyDataSetChanged(); view.setAlpha(1); } }); } }); } privateclassStableArrayAdapterextendsArrayAdapter<String>{ HashMap<String,Integer>mIdMap=newHashMap<String,Integer>(); publicStableArrayAdapter(Contextcontext,inttextViewResourceId, List<String>objects){ super(context,textViewResourceId,objects); for(inti=0;i<objects.size();++i){ mIdMap.put(objects.get(i),i); } } @Override publiclonggetItemId(intposition){ Stringitem=getItem(position); returnmIdMap.get(item); } @Override publicbooleanhasStableIds(){ returntrue; } } }译不动了,直接复制谷歌的翻译了吧,基本意思有了,大体配合着看还是能看懂的。请原谅我的懒~~~~~~~~~

3.Customadapterimplementations

3.1.Developingacustomadapter

The
ArrayAdapter
islimitedasitsupportsonlythemappingof
toString()
tooneviewintherowlayout.Tocontrolthedataassignmentandtosupportseveralviews,youhavetocreateyourcustomadapterimplementation.Forthisyouwouldextendanexistingadapterimplementationorsubclassthe
BaseAdapter
classdirectly.

Tip

Frequentlyyouextend
ArrayAdapter
towriteacustomadapter,asthisissimplerthanextending
BaseAdapter
directly.

所述
ArrayAdapter
有限​​,因为它支持的唯一映射
toString()
中的行布局1图。来控制数据的分配,并支持多个视图,你必须创建自己的自定义适配器实现。为此,将扩大现有的适配器实现或子类
BaseAdapter
直接类。

经常要扩展
ArrayAdapter
编写自定义适配器,因为这是不是扩展简单
BaseAdapter
直接。

3.2.Preparingarowforthelist

Theadapterneedstocreatealayoutforeachrowofthelist.The
ListView
instancecallsthe
getView()
methodontheadapterforeachdataelement.Inthismethodtheadaptercreatestherowlayoutandmapsthedatatotheviewsinthelayout.Thisrootofthelayoutistypicallya
ViewGroup
(layoutmanager)andcontainsseveralotherviews,e.g.,an
ImageView
anda
TextView
.Thefollowinggraphicshowsalistwithdifferentlayoutsforoddandevenrows.该适配器需要创建一个布局为列表中的每一行。所述
ListView
实例调用
getView()
为每个数据元素在适配器上的方法。在该方法中,适配器创建的行布局和数据映射到在布局的观点。布局的这根通常是
ViewGroup
(布局管理器),并包含一些其他意见,例如,一个
ImageView
TextView
。下图显示了不同的布局奇数行和偶数行的列表。Withinthe
getView()
methodyouwouldinflateanXMLbasedlayoutandthensetthecontentoftheindividualviewsbasedontheJavaobjectforthisrow.ToinflatetheXMLlayoutfile,youcanusethe
LayoutInflator
systemservice.

Note

Thislayoutinflatorservicecangetaccessedviathe
getLayoutInflator()
methodoftheactivityorviathe
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)
methodcall.Aftertheadapterinflatedthelayout,itsearchesfortherelevantviewsinthelayoutandfillsthemwiththedata.Theindividualelementsinthelayoutcanbefoundviathe
findViewById()
methodcallonthetoplevelview.
getView()
方法内,你会助长一种基于XML的布局,然后设置基于此行的Java对象的个人意见的内容。膨胀的XML布局文件,你可以使用
LayoutInflator
系统服务。

注意

这种布局充气机服务可以通过获得访问
getLayoutInflator()
活动的方法或通过
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)
方法调用。后适配器膨胀的布局,它搜索的布局有关意见,并填写他们的数据。在布局中的各个元件可以通过找到
findViewById()
上的顶层视图方法调用。

3.3.Exampleforacustomadapter

Thefollowingcodeshowsanimplementationofacustomadapter.Thisadapterassumesthatyouhavetwopngfiles(no.pngandyes.png)inoneofyour
res/drawable
folders.ThecodinginflatesanXMLlayoutfile,findstherelevantviewsinthelayoutandsetstheircontentbasedontheinputdata.下面的代码显示了一个自定义适配器的实现。这个适配器假设你在一个有两个png文件(no.png和yes.png)
res/drawable
文件夹。编码膨胀的XML布局文件,找到有关的意见,在布局,并基于所述输入数据的内容。

packagede.vogella.android.listactivity; importandroid.content.Context; importandroid.view.LayoutInflater; importandroid.view.View; importandroid.view.ViewGroup; importandroid.widget.ArrayAdapter; importandroid.widget.ImageView; importandroid.widget.TextView; publicclassMySimpleArrayAdapterextendsArrayAdapter<String>{ privatefinalContextcontext; privatefinalString[]values; publicMySimpleArrayAdapter(Contextcontext,String[]values){ super(context,R.layout.rowlayout,values); this.context=context; this.values=values; } @Override publicViewgetView(intposition,ViewconvertView,ViewGroupparent){ LayoutInflaterinflater=(LayoutInflater)context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); ViewrowView=inflater.inflate(R.layout.rowlayout,parent,false); TextViewtextView=(TextView)rowView.findViewById(R.id.label); ImageViewimageView=(ImageView)rowView.findViewById(R.id.icon); textView.setText(values[position]); //changetheiconforWindowsandiPhone Strings=values[position]; if(s.startsWith("iPhone")){ imageView.setImageResource(R.drawable.no); }else{ imageView.setImageResource(R.drawable.ok); } returnrowView; } }

3.4.Updatingthedatamodelfromtheadapter

Therowcanalsocontainviewswhichinteractwiththeunderlyingdatamodelviatheadapter.Forexample,youcanhavea
Checkbox
inyourrowlayoutandifthe
Checkbox
isselected,theunderlyingdataischanged.复制真累,后面的一次性贴上了,上下翻动着看吧~~~啊啊啊啊啊啊啊,英文差的悲催娃,翻译个文章都翻译不了~~

4.ListActivityandListFragment

4.1.DefaultcontainerforusingListView

Androidprovidesspecializedfragmentandactivityclassestosimplifylisthandling.Theclassesarethe
ListActivity
classifyouwanttouselistsinactivitiesandthethe
ListFragment
classifyouwanttouselistsinfragments.Youdonothavetoassignalayouttotheseelements.Ifyoudonotdefinealayout,theactivityorfragmentcontainsasingle
ListView
bydefault.
ListActivity
and
ListFragment
alsoallowyoutooverridea
onListItemClick()
methodforhandlingselectionoflistitems.Bothclassesallowyoutosettheadaptertothedefault
ListView
viathe
setListAdapter()
method.Thefollowingexamplecodeshowsasimple
ListFragment
implementation.
packagede.vogella.android.fragments;

importandroid.content.Intent;
importandroid.os.Bundle;
importandroid.view.View;
importandroid.widget.ArrayAdapter;
importandroid.widget.ListView;
importandroid.app.ListFragment;

publicclassMyListFragmentextendsListFragment{

@Override
publicvoidonActivityCreated(BundlesavedInstanceState){
super.onActivityCreated(savedInstanceState);
String[]values=newString[]{"Android","iPhone","WindowsMobile",
"Blackberry","WebOS","Ubuntu","Windows7","MaxOSX",
"Linux","OS/2"};
ArrayAdapter<String>adapter=newArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1,values);
setListAdapter(adapter);
}

@Override
publicvoidonListItemClick(ListViewl,Viewv,intposition,longid){
//dosomethingwiththedata
}
}
Thenextexamplecodedemonstratestheusageofa
ListActivity
.
packagede.vogella.android.listactivity;

importandroid.app.ListActivity;
importandroid.os.Bundle;
importandroid.widget.ArrayAdapter;

publicclassMyListActivityextendsListActivity{
publicvoidonCreate(Bundleicicle){
super.onCreate(icicle);
String[]values=newString[]{"Android","iPhone","WindowsMobile",
"Blackberry","WebOS","Ubuntu","Windows7","MaxOSX",
"Linux","OS/2"};
ArrayAdapter<String>adapter=newArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,values);
setListAdapter(adapter);
}
}

4.2.ListActivityandcustomlayout

Youcanuseacustomlayoutwith
ListActivity
or
ListFragment
.Inthiscasethefragmentoractivitysearchesintheprovidedlayoutfora
ListView
withthepre-defined
android:id
attributesetto
@android:id/list
.Thisusageisdemonstratedbythefollowingcodesnippet.
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>

Warning

IfyoudonotusethisIDordonotincludea
ListView
intoyourlayout,theapplicationcrashesonceyoutrytodisplaytheactivityorthefragment.

4.3.Placeholderforanemptylist

Youcanalsouseaviewwiththe
@android:id/empty
IDinyourlayout.Thecorrespondingactivityandfragmentshowsthisviewautomaticallyifthe
ListView
isemptyandhidesitotherwise.Forexample,youcoulddisplayanerrormessageinsuchaview.

5.Exercise:UsingListViewandListActivity

Thefollowingexercisedemonstrateshowtousea
ListView
inan
ListActivity
.Youusethepredefined
ArrayAdapter
classandanexistingAndroidlayoutfortherows.CreateanewAndroidprojectcalledde.vogella.android.listactivitywiththeactivitycalled
MyListActivity
.Change
MyListActivity
classbasedonthethefollowingcodeexample.Notethatthe
setContentView()
methodisnotused.
packagede.vogella.android.listactivity;

importandroid.app.ListActivity;
importandroid.os.Bundle;
importandroid.view.View;
importandroid.widget.ArrayAdapter;
importandroid.widget.ListView;
importandroid.widget.Toast;

publicclassMyListActivityextendsListActivity{
publicvoidonCreate(Bundleicicle){
super.onCreate(icicle);
String[]values=newString[]{"Android","iPhone","WindowsMobile",
"Blackberry","WebOS","Ubuntu","Windows7","MaxOSX",
"Linux","OS/2"};
ArrayAdapter<String>adapter=newArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,values);
setListAdapter(adapter);
}

@Override
protectedvoidonListItemClick(ListViewl,Viewv,intposition,longid){
Stringitem=(String)getListAdapter().getItem(position);
Toast.makeText(this,item+"selected",Toast.LENGTH_LONG).show();
}
}

6.Exercise:ListActivitywithownlayout

Inourexampleyourwilldefineyourlayoutfortherowsanduseitinyouradapter.Createthe
rowlayout.xml
layoutfileinthe
res/layout
folderofthe
de.vogella.android.listactivity
project.
<?xmlversion="1.0"encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">

<ImageView
android:id="@+id/icon"
android:layout_width="22px"
android:layout_height="22px"
android:layout_marginLeft="4px"
android:layout_marginRight="10px"
android:layout_marginTop="4px"
android:src="@drawable/ic_launcher">
</ImageView>

<TextView
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@+id/label"
android:textSize="20px">
</TextView>

</LinearLayout>
Changeyouractivitysothatisusingthenewlayout.
packagede.vogella.android.listactivity;

importandroid.app.ListActivity;
importandroid.os.Bundle;
importandroid.view.View;
importandroid.widget.ArrayAdapter;
importandroid.widget.ListView;
importandroid.widget.Toast;

publicclassMyListActivityextendsListActivity{
publicvoidonCreate(Bundleicicle){
super.onCreate(icicle);
String[]values=newString[]{"Android","iPhone","WindowsMobile",
"Blackberry","WebOS","Ubuntu","Windows7","MaxOSX",
"Linux","OS/2"};
//useyourcustomlayout
ArrayAdapter<String>adapter=newArrayAdapter<String>(this,
R.layout.rowlayout,R.id.label,values);
setListAdapter(adapter);
}

@Override
protectedvoidonListItemClick(ListViewl,Viewv,intposition,longid){
Stringitem=(String)getListAdapter().getItem(position);
Toast.makeText(this,item+"selected",Toast.LENGTH_LONG).show();
}
}

7.Tutorial:Implementingyourownadapter

Thefollowingusestwoimages"no.png"and"ok.png".Iplaceditinthe"res/drawable-mdpi"folder.Youmustcreateyourownicons.Incaseyoudonotfindanyiconsjustcopy"icon.png"anduseadrawingprogramtochangeitalittlebit.Createtheclass
MySimpleArrayAdapter
whichwillserveasouradapter.
packagede.vogella.android.listactivity;

importandroid.content.Context;
importandroid.view.LayoutInflater;
importandroid.view.View;
importandroid.view.ViewGroup;
importandroid.widget.ArrayAdapter;
importandroid.widget.ImageView;
importandroid.widget.TextView;

publicclassMySimpleArrayAdapterextendsArrayAdapter<String>{
privatefinalContextcontext;
privatefinalString[]values;

publicMySimpleArrayAdapter(Contextcontext,String[]values){
super(context,R.layout.rowlayout,values);
this.context=context;
this.values=values;
}

@Override
publicViewgetView(intposition,ViewconvertView,ViewGroupparent){
LayoutInflaterinflater=(LayoutInflater)context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ViewrowView=inflater.inflate(R.layout.rowlayout,parent,false);
TextViewtextView=(TextView)rowView.findViewById(R.id.label);
ImageViewimageView=(ImageView)rowView.findViewById(R.id.icon);
textView.setText(values[position]);
//ChangetheiconforWindowsandiPhone
Strings=values[position];
if(s.startsWith("Windows7")||s.startsWith("iPhone")
||s.startsWith("Solaris")){
imageView.setImageResource(R.drawable.no);
}else{
imageView.setImageResource(R.drawable.ok);
}

returnrowView;
}
}
Tousethisadapter,changetheactivitytothefollowing.
packagede.vogella.android.listactivity;

importandroid.app.ListActivity;
importandroid.os.Bundle;

publicclassMyListActivityextendsListActivity{
publicvoidonCreate(Bundleicicle){
super.onCreate(icicle);
String[]values=newString[]{"Android","iPhone","WindowsMobile",
"Blackberry","WebOS","Ubuntu","Windows7","MaxOSX",
"Linux","OS/2"};
MySimpleArrayAdapteradapter=newMySimpleArrayAdapter(this,values);
setListAdapter(adapter);
}

}
Ifyourunthisexampleyoushouldgetalistwithdifferenticonsforthecertainelements.

8.ListViewsandperformance

8.1.Motivation

PerformanceisespeciallyimportantonAndroidasusersexpectfastreactiontimes.ComparedtodesktopcomputersanAndroiddeviceisrelativelyslowfromthehardwareperspective.Thispartdescribeshowtoreducetheseoperationstoimplementyourcustomlistadapterefficiently.ThedefaultAndroidadapterslike
ArrayAdapter
arealreadyperformanceoptimized.

8.2.Timeconsumingoperations

EveryviewwhichgetinflatedfromanXMLlayoutfilewillresultinaJavaobject.InflatinglayoutsandcreatingJavaobjectsisexpensivewithregardstotimeandmemoryconsumption.Inadditionusingthe
findViewById()
methodisrelativelytimeconsuming,eventhoughitisnotasbadasXMLinflating.

8.3.Avoidinglayoutinflationandobjectcreation

A
ListView
typicallycontainsmoredatathanthenumberofdisplayedrows.Iftheuserscrollsthelist,thenrowsandtheirassociatedviewsarebeingscrolledoutofthevisiblearea.TheJavaobjectswhichrepresentstherowscanbereusedfornewlyvisiblerows.IfAndroiddeterminesthatarowisnotvisibleanymore,itallowsthe
getView()
oftheadaptermethodtoreusetheassociatedviewviathe
convertView
parameter.Theadaptercanassignnewdatatotheviewscontainedintheviewhierarchyofthe
convertView
.ThisavoidsinflatinganXMLfileandcreatingnewJavaobjects.IncaseAndroidcannotreusearow,theAndroidsystempasses
null
tothe
convertView
parameter.Thereforetheadapterimplementationneedstocheckforthis.

8.4.Viewholderpattern

***iewHolderimplementationallowstoavoidthe
findViewById()
methodinanadapter.A
ViewHolder
classistypicallyastaticinnerclassinyouradapterwhichholdsreferencestotherelevantviews.inyourlayout.Thisreferenceisassignedtotherowviewasatagviathe
setTag()
method.Ifwereceivea
convertView
object,wecangettheinstanceofthe
ViewHolder
viathe
getTag()
methodandassignthenewattributestotheviewsviathe
ViewHolder
reference.Whilethissoundscomplexthisisapproximately15%fasterthenusingthe
findViewById()
method.

8.5.Example

Thefollowingcodeshowsaperformanceoptimizedadapterimplementationwhichreusesexistingviewsandimplementstheholderpattern.
packagede.vogella.android.listactivity;

importandroid.app.Activity;
importandroid.view.LayoutInflater;
importandroid.view.View;
importandroid.view.ViewGroup;
importandroid.widget.ArrayAdapter;
importandroid.widget.ImageView;
importandroid.widget.TextView;

publicclassMyPerformanceArrayAdapterextendsArrayAdapter<String>{
privatefinalActivitycontext;
privatefinalString[]names;

staticclassViewHolder{
publicTextViewtext;
publicImageViewimage;
}

publicMyPerformanceArrayAdapter(Activitycontext,String[]names){
super(context,R.layout.rowlayout,names);
this.context=context;
this.names=names;
}

@Override
publicViewgetView(intposition,ViewconvertView,ViewGroupparent){
ViewrowView=convertView;
//reuseviews
if(rowView==null){
LayoutInflaterinflater=context.getLayoutInflater();
rowView=inflater.inflate(R.layout.rowlayout,null);
//configureviewholder
ViewHolderviewHolder=newViewHolder();
viewHolder.text=(TextView)rowView.findViewById(R.id.TextView01);
viewHolder.image=(ImageView)rowView
.findViewById(R.id.ImageView01);
rowView.setTag(viewHolder);
}

//filldata
ViewHolderholder=(ViewHolder)rowView.getTag();
Strings=names[position];
holder.text.setText(s);
if(s.startsWith("Windows7")||s.startsWith("iPhone")
||s.startsWith("Solaris")){
holder.image.setImageResource(R.drawable.no);
}else{
holder.image.setImageResource(R.drawable.ok);
}

returnrowView;
}
}

9.Storingtheselectionofaview

Bydefaulta
ListView
hasnoselectionmodeactive.Youcanactivateitviathe
setChoiceMode()
methodcall.Pass
ListView.CHOICE_MODE_MULTIPLE
formultipleselectionsor
ListView.CHOICE_MODE_SINGLE
forsingleselectionstothismethod.Togettheselecteditemsofa
ListView
,usethe
getCheckedItemPosition()
forasingleselectionmethodor
listView.getCheckedItemPositions()
formultipleselections..IfyouhavestableID,youcouldalsousethe
getCheckedItemIds()
methodtogettheselectedIDs.Androidalreadyprovidesadefaultlayoutforthis:the
android.R.layout.simple_list_item_multiple_choice
layoutwhichcontainsaconfigured
CheckedTextView
view.Thefollowingactivitiesdemonstratehowtousetheseselectionmodes.Ifyouusethesemodes,the
ListView
storestheselectedvalues.Itisnotpersistedinyourdatamodel.
packagecom.vogella.android.listview.selection.multi;

importandroid.app.ListActivity;
importandroid.os.Bundle;
importandroid.view.Menu;
importandroid.view.MenuItem;
importandroid.widget.ArrayAdapter;
importandroid.widget.ListView;
importandroid.widget.Toast;

importcom.vogella.android.listview.selection.R;

publicclassMainActivityextendsListActivity{

@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
String[]values=newString[]{"a","b","c","d","e","f","g",
"h","i","j","k","l","m","n","o","p","q","r","s",
"t","u","w","x","y","z"};

ArrayAdapter<String>adapter=newArrayAdapter<String>(this,
android.R.layout.simple_list_item_multiple_choice,values);
setListAdapter(adapter);
getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
}

@Override
publicbooleanonCreateOptionsMenu(Menumenu){
getMenuInflater().inflate(R.menu.main,menu);
returntrue;
}

@Override
publicbooleanonOptionsItemSelected(MenuItemitem){
Toast.makeText(this,
String.valueOf(getListView().getCheckedItemCount()),
Toast.LENGTH_LONG).show();
returntrue;
}
}
packagecom.vogella.android.listview.selection.single;

importandroid.app.ListActivity;
importandroid.os.Bundle;
importandroid.view.Menu;
importandroid.view.MenuItem;
importandroid.widget.ArrayAdapter;
importandroid.widget.ListView;
importandroid.widget.Toast;

publicclassMainActivityextendsListActivity{

@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
String[]values=newString[]{"a","b","c","d","e","f","g",
"h","i","j","k","l","m","n","o","p","q","r","s",
"t","u","w","x","y","z"};

ArrayAdapter<String>adapter=newArrayAdapter<String>(this,
android.R.layout.simple_list_item_single_choice,values);
setListAdapter(adapter);
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
}

@Override
publicbooleanonCreateOptionsMenu(Menumenu){
getMenuInflater().inflate(R.menu.main,menu);
returntrue;
}

@Override
publicbooleanonOptionsItemSelected(MenuItemitem){
Toast.makeText(this,
String.valueOf(getListView().getCheckedItemCount()),
Toast.LENGTH_LONG).show();
returntrue;
}
}

10.ContextualactionmodeforListViews

ThefollowingassumesthatyoualreadyfamiliarwiththeconceptoftheActionBarandcontextualactionmodeingeneral.Thispartwillexplainhowtousecontextualactionmodefora
ListView
selection.Toassignacontextualactionmodetoalongclickonanindividualitem,usethemethod
setOnItemLongClickListener()
on
ListView
.Thismethodsincludesinformationabouttheselecteditem.Inthismethodyoucanstartthe
ActionMode
.Thefollowingexamplesdemonstratethat.ItassumesthatyouhaveamenuXMLfiledefinedcalled
rowselection.xml
andthatthismenucontainsoneentrywiththe
@+id/menuitem1_show
ID.
packagede.vogella.android.listactivity;

importandroid.app.ListActivity;
importandroid.os.Bundle;
importandroid.view.ActionMode;
importandroid.view.Menu;
importandroid.view.MenuInflater;
importandroid.view.MenuItem;
importandroid.view.View;
importandroid.widget.AdapterView;
importandroid.widget.AdapterView.OnItemLongClickListener;
importandroid.widget.Toast;

publicclassMyListActivityActionbarextendsListActivity
implementsActionMode.Callback{

protectedObjectmActionMode;
publicintselectedItem=-1;

@Override
publicvoidonCreate(Bundleicicle){
super.onCreate(icicle);
String[]values=newString[]{"Android",
"iPhone","WindowsMobile",
"Blackberry","WebOS","Ubuntu",
"Windows7","MaxOSX","Linux","OS/2",
"Ubuntu","Windows7","MaxOSX",
"Linux","OS/2","Ubuntu",
"Windows7","MaxOSX",
"Linux","OS/2"};

MySimpleArrayAdapteradapter=newMySimpleArrayAdapter(this,values);
setListAdapter(adapter);

getListView().setOnItemLongClickListener(newOnItemLongClickListener(){

@Override
publicbooleanonItemLongClick(AdapterView<?>parent,Viewview,intposition,longid){

if(mActionMode!=null){
returnfalse;
}
selectedItem=position;

//StarttheCABusingtheActionMode.Callbackdefinedabove
MyListActivityActionbar.this.startActionMode(MyListActivityActionbar.this);
view.setSelected(true);
returntrue;
}
});
}

privatevoidshow(){
Toast.makeText(MyListActivityActionbar.this,String.valueOf(selectedItem),Toast.LENGTH_LONG).show();
}

//Calledwhentheactionmodeiscreated;startActionMode()wascalled
@Override
publicbooleanonCreateActionMode(ActionModemode,Menumenu){
//Inflateamenuresourceprovidingcontextmenuitems
MenuInflaterinflater=mode.getMenuInflater();
//Assumesthatyouhave"contexual.xml"menuresources
inflater.inflate(R.menu.rowselection,menu);
returntrue;
}

//Calledeachtimetheactionmodeisshown.Alwayscalledafter
//onCreateActionMode,but
//maybecalledmultipletimesifthemodeisinvalidated.
@Override
publicbooleanonPrepareActionMode(ActionModemode,Menumenu){
returnfalse;//Returnfalseifnothingisdone
}

//Calledwhentheuserselectsacontextualmenuitem
@Override
publicbooleanonActionItemClicked(ActionModemode,MenuItemitem){
switch(item.getItemId()){
caseR.id.menuitem1_show:
show();
//Actionpicked,soclosetheCAB
mode.finish();
returntrue;
default:
returnfalse;
}
}

//Calledwhentheuserexitstheactionmode
@Override
publicvoidonDestroyActionMode(ActionModemode){
mActionMode=null;
selectedItem=-1;
}

}
Ifyoustartyourapplicationandlongpressonaniteminthelist,yougetyourcontextualactionbar.

11.Implementingundoforanaction

11.1.Whenshouldyouofferanundoaction?

Itisgoodpracticetoallowtheusertoundocriticalactions.Suchacriticalactionis,forexample,thedeletionoflistitems.Aprovenpatterntohandlethisundooptionistoofferaselectionattheendofthescreen.Thisselectionvanishesafterapredefinedtimeoroncetheusercontinuestointeractwiththeapplication.Forexample,theGmailapplicationimplementssuchabehavior.

11.2.Example

Thefollowingdescriptioncontainsanexampleforimplementinganundoaction.Itusesananimationtophaseouttheundobuttonautomaticallyoutafterawhile.Forthisexamplecreateanewprojectcalledcom.vogella.android.userinterface.undobasedontheBlankTemplatetemplate.Createthefollowinglayoutforyouractivity.Itusesa
FrameLayout
toshowtwodifferentpartsoftheuserinterface.Thebuttonbarisinitiallyhidden.Thebuttonusesadrawable.Eitheraddsuchadrawabletoyourprojectorremovethereference.
<FrameLayoutxmlns: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">

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
</RelativeLayout>

<LinearLayout
android:id="@+id/undobar"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:layout_margin="20dp"
android:alpha="100"
android:background="#808080"
android:dividerPadding="11dp"
android:padding="4dp">

<TextView
android:id="@+id/undobar_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Deleted"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#fff"/>

<Button
android:id="@+id/undobar_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:onClick="onClick"
android:background="#808080"
android:drawableLeft="@drawable/ic_undobar_undo"
android:text="Undo"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#fff"/>
</LinearLayout>

</FrameLayout>
Changeyouractivitysothatitissimilartothefollowingcode.TheAndroidprojectwizardinEclipsealreadygeneratedan
ActionBar
entry.Thisentryisusedinthefollowingcode.Ifindoubt,createyourown
ActionBar
entry.
packagecom.vogella.android.userinterface.undo;

importandroid.app.Activity;
importandroid.os.Bundle;
importandroid.view.Menu;
importandroid.view.MenuItem;
importandroid.view.View;
importandroid.widget.ArrayAdapter;
importandroid.widget.ListView;
importandroid.widget.Toast;

importcom.vogella.android.actionbar.undo.R;

publicclassMainActivityextendsActivity{

privateViewviewContainer;

@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListViewl=(ListView)findViewById(R.id.listview);
String[]values=newString[]{"Ubuntu","Android","iPhone",
"Windows","Ubuntu","Android","iPhone","Windows"};
ArrayAdapter<String>adapter=newArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,values);
viewContainer=findViewById(R.id.undobar);
l.setAdapter(adapter);
}

@Override
publicbooleanonCreateOptionsMenu(Menumenu){
//Inflatethemenu;thisaddsitemstotheactionbarifitispresent.
getMenuInflater().inflate(R.menu.activity_main,menu);
returntrue;
}

@Override
publicbooleanonOptionsItemSelected(MenuItemitem){
showUndo(viewContainer);
returntrue;
}

publicvoidonClick(Viewview){
Toast.makeText(this,"Deletionundone",Toast.LENGTH_LONG).show();
viewContainer.setVisibility(View.GONE);
}

publicstaticvoidshowUndo(finalViewviewContainer){
viewContainer.setVisibility(View.VISIBLE);
viewContainer.setAlpha(1);
viewContainer.animate().alpha(0.4f).setDuration(5000)
.withEndAction(newRunnable(){

@Override
publicvoidrun(){
viewContainer.setVisibility(View.GONE);
}
});

}
}
IfyouselecttheentryintheActionBar,thebuttonbarbecomesvisiblefor5seconds.

12.PerformanceOptimization

Thefollowingwillimplementaperformanceoptimizedversionoftheadapterfromthepreviousexample.Createthefollowing
MyPerformanceArrayAdapter
class.
packagede.vogella.android.listactivity;

importandroid.app.Activity;
importandroid.view.LayoutInflater;
importandroid.view.View;
importandroid.view.ViewGroup;
importandroid.widget.ArrayAdapter;
importandroid.widget.ImageView;
importandroid.widget.TextView;

publicclassMyPerformanceArrayAdapterextendsArrayAdapter<String>{
privatefinalActivitycontext;
privatefinalString[]names;

staticclassViewHolder{
publicTextViewtext;
publicImageViewimage;
}

publicMyPerformanceArrayAdapter(Activitycontext,String[]names){
super(context,R.layout.rowlayout,names);
this.context=context;
this.names=names;
}

@Override
publicViewgetView(intposition,ViewconvertView,ViewGroupparent){
ViewrowView=convertView;
//reuseviews
if(rowView==null){
LayoutInflaterinflater=context.getLayoutInflater();
rowView=inflater.inflate(R.layout.rowlayout,null);
//configureviewholder
ViewHolderviewHolder=newViewHolder();
viewHolder.text=(TextView)rowView.findViewById(R.id.TextView01);
viewHolder.image=(ImageView)rowView
.findViewById(R.id.ImageView01);
rowView.setTag(viewHolder);
}

//filldata
ViewHolderholder=(ViewHolder)rowView.getTag();
Strings=names[position];
holder.text.setText(s);
if(s.startsWith("Windows7")||s.startsWith("iPhone")
||s.startsWith("Solaris")){
holder.image.setImageResource(R.drawable.no);
}else{
holder.image.setImageResource(R.drawable.ok);
}

returnrowView;
}
}
Useyournewadapterinyouractivity.Ifyouruntheapplicationitshouldlookthesamebutitwillbemuchfaster,especiallyforlargedatasets.
packagede.vogella.android.listactivity;

importandroid.app.ListActivity;
importandroid.os.Bundle;

publicclassMyListActivityextendsListActivity{
publicvoidonCreate(Bundleicicle){
super.onCreate(icicle);
String[]values=newString[]{"Android","iPhone","WindowsMobile",
"Blackberry","WebOS","Ubuntu","Windows7","MaxOSX",
"Linux","OS/2"};
setListAdapter(newMyPerformanceArrayAdapter(this,values));
}

}

13.Tutorial:HowtodisplaytwoitemsinaListView

Youcanusethe
SimpleAdapter
classtoshowthedataoftwoelements.ThisclassexpectsaArrayofStrings(
from
data)inwhichthefieldsoftheinputdataaredefined.ItalsorequiresaArrayofintswhichdefinestheIDsofthewidgetsinthelayoutfortherowtowhichthesefieldsaremapped.TheactualdataisthenalistofMaps.TheMapdefinesforeachfieldinthefromdataavalue.ThefollowingshowsanexamplewhichreusesanpredefinedlayoutfromAndroidfortherow.
packagede.vogella.android.listactivity;

importjava.util.ArrayList;
importjava.util.HashMap;
importjava.util.Map;

importandroid.app.ListActivity;
importandroid.os.Bundle;
importandroid.widget.SimpleAdapter;

publicclassMyTwoListItemsActivityextendsListActivity{
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
ArrayList<Map<String,String>>list=buildData();
String[]from={"name","purpose"};
int[]to={android.R.id.text1,android.R.id.text2};

SimpleAdapteradapter=newSimpleAdapter(this,list,
android.R.layout.simple_list_item_2,from,to);
setListAdapter(adapter);
}

privateArrayList<Map<String,String>>buildData(){
ArrayList<Map<String,String>>list=newArrayList<Map<String,String>>();
list.add(putData("Android","Mobile"));
list.add(putData("Windows7","Windows7"));
list.add(putData("iPhone","iPhone"));
returnlist;
}

privateHashMap<String,String>putData(Stringname,Stringpurpose){
HashMap<String,String>item=newHashMap<String,String>();
item.put("name",name);
item.put("purpose",purpose);
returnitem;
}

}

14.SelectingmultipleitemsintheListView

14.1.InteractionbetweenthemodelandListview

Frequentlyyouneedtoselectitemsinyour
ListView
.Astherowofthe
ListView
aregettingrecycledyoucannotstoretheselectiononthe
View
level.Selectionisjustonepossibleexamplebutyoucanimangeotherinteractionbetweenyourrowandmodel.Topersisttheselectionyouhavetoupdateyourdatamodelwiththeselectedstate.Toupdatethedatamodelinyour
ListView
youdefineyourown
Adapter
class.Inthisadapterclassyouattachalistenertothe
View
whichisresponsibleforselectingthemodelelement.IfselectedyouupdatethestateinthemodelwhichyoucanaddasatagtotheViewtohaveaccesstoit.ThefollowingexampledemonstrateshowtousestandardJavaobjectandhowtointeractfromthe
Views
withthemodel.

14.2.Tutorial:DomainModelandRowsinteraction

Continuetousethe
de.vogella.android.listactivity
project.Createthefollowing
Model
whichholdthenameandtheinformationifthiselementiscurrentlyselected.
packagede.vogella.android.listactivity;

publicclassModel{

privateStringname;
privatebooleanselected;

publicModel(Stringname){
this.name=name;
selected=false;
}

publicStringgetName(){
returnname;
}

publicvoidsetName(Stringname){
this.name=name;
}

publicbooleanisSelected(){
returnselected;
}

publicvoidsetSelected(booleanselected){
this.selected=selected;
}

}
Createthefollowingnewlayoutfilecalled
rowbuttonlayout.xml
.
<?xmlversion="1.0"encoding="utf-8"?>
<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<TextView
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@+id/label"
android:textSize="30px">
</TextView>

<CheckBox
android:id="@+id/check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginLeft="4px"
android:layout_marginRight="10px">
</CheckBox>

</RelativeLayout>
Createthefollowing
Adapter
.Thisadapteraddsalisteneronthe
Checkbox
view.Ifthecheckboxisselectedtheunderlyingdataofthemodelischanged.
Checkbox
getsthecorrespondingmodelelementassignedviathe
getTag()
method.
packagede.vogella.android.listactivity;

importjava.util.List;

importandroid.app.Activity;
importandroid.view.LayoutInflater;
importandroid.view.View;
importandroid.view.ViewGroup;
importandroid.widget.ArrayAdapter;
importandroid.widget.CheckBox;
importandroid.widget.CompoundButton;
importandroid.widget.TextView;

publicclassInteractiveArrayAdapterextendsArrayAdapter<Model>{

privatefinalList<Model>list;
privatefinalActivitycontext;

publicInteractiveArrayAdapter(Activitycontext,List<Model>list){
super(context,R.layout.rowbuttonlayout,list);
this.context=context;
this.list=list;
}

staticclassViewHolder{
protectedTextViewtext;
protectedCheckBoxcheckbox;
}

@Override
publicViewgetView(intposition,ViewconvertView,ViewGroupparent){
Viewview=null;
if(convertView==null){
LayoutInflaterinflator=context.getLayoutInflater();
view=inflator.inflate(R.layout.rowbuttonlayout,null);
finalViewHolderviewHolder=newViewHolder();
viewHolder.text=(TextView)view.findViewById(R.id.label);
viewHolder.checkbox=(CheckBox)view.findViewById(R.id.check);
viewHolder.checkbox
.setOnCheckedChangeListener(newCompoundButton.OnCheckedChangeListener(){

@Override
publicvoidonCheckedChanged(CompoundButtonbuttonView,
booleanisChecked){
Modelelement=(Model)viewHolder.checkbox
.getTag();
element.setSelected(buttonView.isChecked());

}
});
view.setTag(viewHolder);
viewHolder.checkbox.setTag(list.get(position));
}else{
view=convertView;
((ViewHolder)view.getTag()).checkbox.setTag(list.get(position));
}
ViewHolderholder=(ViewHolder)view.getTag();
holder.text.setText(list.get(position).getName());
holder.checkbox.setChecked(list.get(position).isSelected());
returnview;
}
}
Finallychangeyouractivitytothefollowing.
packagede.vogella.android.listactivity;

importjava.util.ArrayList;
importjava.util.List;

importandroid.app.ListActivity;
importandroid.os.Bundle;
importandroid.widget.ArrayAdapter;

publicclassMyListextendsListActivity{

/**Calledwhentheactivityisfirstcreated.*/
publicvoidonCreate(Bundleicicle){
super.onCreate(icicle);
//createanarrayofStrings,thatwillbeputtoourListActivity
ArrayAdapter<Model>adapter=newInteractiveArrayAdapter(this,
getModel());
setListAdapter(adapter);
}

privateList<Model>getModel(){
List<Model>list=newArrayList<Model>();
list.add(get("Linux"));
list.add(get("Windows7"));
list.add(get("Suse"));
list.add(get("Eclipse"));
list.add(get("Ubuntu"));
list.add(get("Solaris"));
list.add(get("Android"));
list.add(get("iPhone"));
//Initiallyselectoneoftheitems
list.get(1).setSelected(true);
returnlist;
}

privateModelget(Strings){
returnnewModel(s);
}

}
Ifyoustartyourappyoushouldbeabletoflagitems.Thesechangeswillbereflectedinyourmodel.

15.ImplementinganexpandableListView

15.1.ExpandableListView

The
ExpandableListView
issimilarto
ListView
butallowyoutodefinegroupsanddetailsforthisgroup.
ExpandableListView
expectsandadapteroftype
BaseExpandableListAdapter
.Inthiscaseyouhavetodefinetwolayouts,oneforthegroupandanotheroneforthedetailsrow.

15.2.ExpandableListViewexample

Inthefollowingexampleyoucreateanexpandablelistviewsimilartothefollowingscreenshot.Createaprojectcalledcom.vogella.android.listview.expandablewiththeactivitycalled
MainActivity
.Createoradjustthefollowinglayoutfiles.First
layout/activity_main.xml
.
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity">

<ExpandableListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ExpandableListView>

</LinearLayout>
Afterwardscreate
layout/listrow_group.xml
.
<CheckedTextViewxmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="?android:attr/listPreferredItemHeight"
android:layout_marginLeft="8dp"
android:drawableRight="@drawable/ic_launcher"
android:gravity="left"
android:paddingLeft="32dp"
android:paddingTop="8dp"
android:text="Test"
android:textSize="14sp"
android:textAlignment="textEnd"
android:textStyle="bold"/>
Thelastrequiredlayoutis
layout/listrow_details.xml
.
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="40dp"
android:clickable="true"
android:orientation="vertical"
android:paddingLeft="40dp"
tools:context=".MainActivity">

<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_launcher"
android:drawablePadding="5dp"
android:gravity="center_vertical"
android:text="@string/hello_world"
android:textSize="14sp"
android:textStyle="bold">
</TextView>

<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@android:color/black"/>

</LinearLayout>
Createthefollowingclasswhichholdyourdomainmodelforthe
ExpandableListView
.
packagecom.vogella.android.listview.expandable;

importjava.util.ArrayList;
importjava.util.List;

publicclassGroup{

publicStringstring;
publicfinalList<String>children=newArrayList<String>();

publicGroup(Stringstring){
this.string=string;
}

}
Finallycreatetheadapterasdescribedbythefollowinglistingandchangetheactivitytothecodeprovidedbelow.
packagecom.vogella.android.listview.expandable;

importandroid.app.Activity;
importandroid.util.SparseArray;
importandroid.view.LayoutInflater;
importandroid.view.View;
importandroid.view.View.OnClickListener;
importandroid.view.ViewGroup;
importandroid.widget.BaseExpandableListAdapter;
importandroid.widget.CheckedTextView;
importandroid.widget.TextView;
importandroid.widget.Toast;

publicclassMyExpandableListAdapterextendsBaseExpandableListAdapter{

privatefinalSparseArray<Group>groups;
publicLayoutInflaterinflater;
publicActivityactivity;

publicMyExpandableListAdapter(Activityact,SparseArray<Group>groups){
activity=act;
this.groups=groups;
inflater=act.getLayoutInflater();
}

@Override
publicObjectgetChild(intgroupPosition,intchildPosition){
returngroups.get(groupPosition).children.get(childPosition);
}

@Override
publiclonggetChildId(intgroupPosition,intchildPosition){
return0;
}

@Override
publicViewgetChildView(intgroupPosition,finalintchildPosition,
booleanisLastChild,ViewconvertView,ViewGroupparent){
finalStringchildren=(String)getChild(groupPosition,childPosition);
TextViewtext=null;
if(convertView==null){
convertView=inflater.inflate(R.layout.listrow_details,null);
}
text=(TextView)convertView.findViewById(R.id.textView1);
text.setText(children);
convertView.setOnClickListener(newOnClickListener(){
@Override
publicvoidonClick(Viewv){
Toast.makeText(activity,children,
Toast.LENGTH_SHORT).show();
}
});
returnconvertView;
}

@Override
publicintgetChildrenCount(intgroupPosition){
returngroups.get(groupPosition).children.size();
}

@Override
publicObjectgetGroup(intgroupPosition){
returngroups.get(groupPosition);
}

@Override
publicintgetGroupCount(){
returngroups.size();
}

@Override
publicvoidonGroupCollapsed(intgroupPosition){
super.onGroupCollapsed(groupPosition);
}

@Override
publicvoidonGroupExpanded(intgroupPosition){
super.onGroupExpanded(groupPosition);
}

@Override
publiclonggetGroupId(intgroupPosition){
return0;
}

@Override
publicViewgetGroupView(intgroupPosition,booleanisExpanded,
ViewconvertView,ViewGroupparent){
if(convertView==null){
convertView=inflater.inflate(R.layout.listrow_group,null);
}
Groupgroup=(Group)getGroup(groupPosition);
((CheckedTextView)convertView).setText(group.string);
((CheckedTextView)convertView).setChecked(isExpanded);
returnconvertView;
}

@Override
publicbooleanhasStableIds(){
returnfalse;
}

@Override
publicbooleanisChildSelectable(intgroupPosition,intchildPosition){
returnfalse;
}
}
packagecom.vogella.android.listview.expandable;

importjava.util.ArrayList;

importandroid.app.Activity;
importandroid.os.Bundle;
importandroid.util.SparseArray;
importandroid.view.Menu;
importandroid.widget.ExpandableListView;

publicclassMainActivityextendsActivity{
//moreefficientthanHashMapformappingintegerstoobjects
SparseArray<Group>groups=newSparseArray<Group>();

@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
createData();
ExpandableListViewlistView=(ExpandableListView)findViewById(R.id.listView);
MyExpandableListAdapteradapter=newMyExpandableListAdapter(this,
groups);
listView.setAdapter(adapter);
}

publicvoidcreateData(){
for(intj=0;j<5;j++){
Groupgroup=newGroup("Test"+j);
for(inti=0;i<5;i++){
group.children.add("SubItem"+i);
}
groups.append(j,group);
}
}

}

16.Tutorial:Miscellaneous

16.1.Addingalongclicklistenertothelistitems

Youcanalsoadda
LongItemClickListener
tothe
View
.Forthisreceivethe
ListView
viathe
getListVIew()
methodandsetthe
LongItemClickListener
viathesetOnItemLongClickListener()method.
packagede.vogella.android.listactivity;

importandroid.app.ListActivity;
importandroid.os.Bundle;
importandroid.view.View;
importandroid.widget.AdapterView;
importandroid.widget.AdapterView.OnItemLongClickListener;
importandroid.widget.ArrayAdapter;
importandroid.widget.ListView;
importandroid.widget.Toast;

publicclassMyListextendsListActivity{

/**Calledwhentheactivityisfirstcreated.*/
publicvoidonCreate(Bundleicicle){
super.onCreate(icicle);
//createanarrayofStrings,thatwillbeputtoourListActivity
String[]names=newString[]{"Linux","Windows7","Eclipse","Suse",
"Ubuntu","Solaris","Android","iPhone"};
ArrayAdapter<String>adapter=newMyPerformanceArrayAdapter(this,names);
setListAdapter(adapter);
ListViewlist=getListView();
list.setOnItemLongClickListener(newOnItemLongClickListener(){

@Override
publicbooleanonItemLongClick(AdapterView<?>parent,Viewview,
intposition,longid){
Toast.makeText(MyList.this,
"Iteminposition"+position+"clicked",
Toast.LENGTH_LONG).show();
//Returntruetoconsumetheclickevent.Inthiscasethe
//onListItemClicklistenerisnotcalledanymore.
returntrue;
}
});
}

@Override
protectedvoidonListItemClick(ListViewl,Viewv,intposition,longid){
super.onListItemClick(l,v,position,id);
//Gettheitemthatwasclicked
Objecto=this.getListAdapter().getItem(position);
Stringkeyword=o.toString();
Toast.makeText(this,"Youselected:"+keyword,Toast.LENGTH_SHORT)
.show();

}

}

16.2.HeaderandFooter

Youcanofcourseputarbitrary
Views
elementsaroundyourListView.Forexampleyoucandefinealayoutwithtwo
TextViews
anda
ListView
betweenthem.InthiscasethetwoTextViewswillalwaysbevisibleabovetheList(header)andtheotherwillbevisiblebelowtheListView.Ifyouwanttodisplayalistheaderorlistfooteronlyattheseethebeginningorendofthelistyoucanusethe
addHeaderView()
methodor
addFooterView()
methodonthe
ListView
class.
packagede.vogella.android.listactivity;

importandroid.app.ListActivity;
importandroid.os.Bundle;
importandroid.view.View;
importandroid.widget.ArrayAdapter;
importandroid.widget.ListView;

publicclassMyListextendsListActivity{

/**Calledwhentheactivityisfirstcreated.*/
publicvoidonCreate(Bundleicicle){
super.onCreate(icicle);
//createanarrayofStrings,thatwillbeputtoourListActivity
String[]names=newString[]{"Linux","Windows7","Eclipse","Suse",
"Ubuntu","Solaris","Android","iPhone","Linux","Windows7",
"Eclipse","Suse","Ubuntu","Solaris","Android","iPhone"};
Viewheader=getLayoutInflater().inflate(R.layout.header,null);
Viewfooter=getLayoutInflater().inflate(R.layout.footer,null);
ListViewlistView=getListView();
listView.addHeaderView(header);
listView.addFooterView(footer);
setListAdapter(newArrayAdapter<String>(this,
android.R.layout.simple_list_item_single_choice,
android.R.id.text1,names));

}
}

17.SimpleCursorAdapter

Incaseyouworkwithacontentproviderordirectlywiththedatabaseyoucanusethe
SimpleCursorAdapter
todefinethedataforyour
ListView
.ThefollowingwilldemonstrateshowtoaccesstheContactsContentProvider.CreateanewAndroidprojectcalled"de.vogella.android.listactivity.cursor"withtheactivitycalledMyListActivity.Change
MyListActivity
tothefollowing.
packagede.vogella.android.listactivity.cursor;

importandroid.app.ListActivity;
importandroid.database.Cursor;
importandroid.net.Uri;
importandroid.os.Bundle;
importandroid.provider.ContactsContract;
importandroid.widget.ListAdapter;
importandroid.widget.SimpleCursorAdapter;

publicclassMyListActivityextendsListActivity{
/**Calledwhentheactivityisfirstcreated.*/
@Override
publicvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
CursormCursor=getContacts();
startManagingCursor(mCursor);
//nowcreateanewlistadapterboundtothecursor.
//SimpleListAdapterisdesignedforbindingtoaCursor.
ListAdapteradapter=newSimpleCursorAdapter(this,//Context.
android.R.layout.two_line_list_item,//Specifytherowtemplate
//touse(here,two
//columnsboundtothe
//tworetrievedcursor
//rows).
mCursor,//Passinthecursortobindto.
//Arrayofcursorcolumnstobindto.
newString[]{ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME},
//Parallelarrayofwhichtemplateobjectstobindtothose
//columns.
newint[]{android.R.id.text1,android.R.id.text2});

//Bindtoournewadapter.
setListAdapter(adapter);
}

privateCursorgetContacts(){
//Runquery
Uriuri=ContactsContract.Contacts.CONTENT_URI;
String[]projection=newString[]{ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME};
Stringselection=ContactsContract.Contacts.IN_VISIBLE_GROUP+"='"
+("1")+"'";
String[]selectionArgs=null;
StringsortOrder=ContactsContract.Contacts.DISPLAY_NAME
+"COLLATELOCALIZEDASC";

returnmanagedQuery(uri,projection,selection,selectionArgs,
sortOrder);
}

}
Makesureyougiveyourapplicationthepermissiontoreadthecontacts.(UsesPermissions"android.permission.READ_CONTACTS"inAndroidManifest.xml)

18.AdditionalOpenSourcelibraries

SometimeshavingtopressarefreshbuttonontheActionBartorefreshdatacanbeannoyingfortheuser.ChrisBaneshasimplementedanOpenSourcelibrarytoimplementthepulltorefreshpatternfora
Listview
.https://github.com/chrisbanes/Android-PullToRefresh.AlsoyoumaywanttousetheswipetodismissgesturetodeleteitemsfromaListView.RomanNurikprovidesanexampleforthisatAndroidswipe-to-dismisslibrarywhichJakeWhartonbackportedtoearlierAndroidreleasesatSwipeToDismissNOA.!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

4.ListActivity和ListFragment

4.1。使用ListView的默认容器

Android提供了专门的片段和活动课,以简化处理列表。该班​​是
ListActivity
类,如果你想使用列表中的活动和在
ListFragment
,如果你想使用列表中的片段类。你不必布局分配给这些元素。如果你没有定义布局,活动或片段包含一个
ListView
默认。
ListActivity
ListFragment
还允许您重写
onListItemClick()
方法来处理选择列表中的项目。这两个类允许您设置适配器默认
ListView
通过
setListAdapter()
方法。下面的示例代码显示了一个简单的
ListFragment
实现。
接下来的示例代码演示的使用
ListActivity

4.2。ListActivity和自定义布局

你可以使用一个自定义布局
ListActivity
ListFragment
。在这种情况下,该片段或活性的搜索在为提供布局
ListView
与预先定义
android:id
属性设置为
@android:id/list
。这种用法表现在下面的代码片段。

警告

如果你不使用这个ID或者不包括
ListView
到您的布局,一旦你尝试以显示活动或片段的应用程序崩溃。

4.3。占位符空列表

您还可以使用与视图
@android:id/empty
在布局ID。相应的活动和片段显示了这一观点自动如果
ListView
是空的,否则隐藏它。例如,你可以在这样一个视图中显示错误消息。

5.练习:使用ListView和ListActivity

下面的练习演示如何使用
ListView
中的
ListActivity
。可以使用预定义的
ArrayAdapter
类和用于行现有机器人布局。创建一个名为de.vogella.android.listactivity与所谓的活动新的Android项目
MyListActivity
。改变
MyListActivity
基础上,下面的代码示例类。需要注意的是
setContentView()
未使用的方法。

6.运动:ListActivity有自己的布局

在我们的例子中你将定义你的布局行,并用它在你的适配器。创建
rowlayout.xml
在布局文件
res/layout
的文件夹
de.vogella.android.listactivity
项目。
所以在使用新的布局改变你的活动。

7.教程:实现自己的适配器

下面使用两个图像“no.png”和“ok.png”。我把它放在了“RES/绘制-MDPI”文件夹中。你必须创建自己的图标。如果你没有找到任何图标只是复制“的icon.png”,并使用绘图程序来改变它一点点。创建类
MySimpleArrayAdapter
这将作为我们的适配器。
要使用此适配器,活动更改为以下。
如果你运行这个例子,你应该得到不同的图标的某些元素的列表。

8.列表视图和性能

8.1。动机

性能在Android上尤其重要,因为用户所期望的快速的反应时间。与台式机相比Android设备是从硬件的角度来看相对缓慢。这部分介绍如何减少这些操作有效地实现您的自定义列表适配器。默认的Android适配器像
ArrayAdapter
已经优化性能。

8.2。耗时的操作

这从一个XML布局文件得到充气每个视图将导致Java对象。充气布局和创建Java对象是昂贵的问候时间和内存消耗。除了​​使用
findViewById()
方法比较费时,即使它不是那么糟糕,因为XML膨胀。

8.3。避免布局通胀和对象创建

一个
ListView
通常包含比显示的行数更多的数据。如果用户滚动列表中,则行和与其相关的意见正在滚动出可视区域的。它代表行的Java对象可以再次用于新的可见行。如果Android的确定一个行不再可见,它允许
getView()
适配器方法重用通过相关视图
convertView
参数。该适配器可以将新的数据包含在的视图层次的意见
convertView
。这避免了膨胀的XML文件,并创建新的Java对象。在Android的情况下,不能再使用一排,Android系统传递
null
convertView
参数。因此适配器实现需要检查这一点。

8.4。查看持有人模式

一个ViewHolder实现允许避免
findViewById()
在适配器的方法。一
ViewHolder
类通常是在你的适配器持有引用相关意见静态内部类。在您的布局。该参考分配给行视图,经由一个标签
setTag()
方法。如果我们收到
convertView
对象,我们可以得到的实例
ViewHolder
通过
getTag()
方法,并指定新的属性通过意见
ViewHolder
参考。虽然这听起来复杂,这是更快的约15%,然后使用
findViewById()
方法。

8.5。例

下面的代码显示了一个性能优化的适配器实现其重用现有的意见,并实现了持有人格局。

9.保存视图的选择

默认情况下
ListView
没有选择模式激活。您可以通过激活它
setChoiceMode()
方法调用。通过
ListView.CHOICE_MODE_MULTIPLE
多个选择或
ListView.CHOICE_MODE_SINGLE
单选择此方法。要获得的所选项目
ListView
,使用
getCheckedItemPosition()
为一个单一的选择方法或
listView.getCheckedItemPositions()
进行多选。。如果你有稳定的ID,你也可以使用
getCheckedItemIds()
方法来获得所选择的ID。安卓已经​​提供了这样的默认布局:在
android.R.layout.simple_list_item_multiple_choice
布局,其中包含一个配置
CheckedTextView
视图。以下活动演示了如何使用这些选择模式。如果你使用这些模式,
ListView
存储选择的值。它不坚持你的数据模型。

10.上下文动作模式列表视图

以下假定您已经熟悉了动作条的一般概念和上下文的行动模式。这部分将介绍如何使用上下文的行动模式的
ListView
选择。要在单个项目分配上下文的动作模式,长按,使用的方法
setOnItemLongClickListener()
ListView
。该方法包括对所选项目的信息。在这种方法中,你可以开始
ActionMode
。下面的实施例证明。它假定您已经定义了一个名为菜单XML文件
rowselection.xml
而这个菜单包含一个条目与
@+id/menuitem1_show
ID。
如果你启动应用程序,并长按列表中的一个项目,你会得到你的上下文行动吧。

11.实施撤消一个动作

11.1。当你要提供一个撤消操作?

这是很好的做法,以允许用户撤消关键行动。这样一个关键的动作是,例如,删除的列表项。甲证明图案来处理这种撤消选项是提供一种选择在屏幕的末端。后的预定时间该选择消失或者一旦用户继续与应用程序交互。例如,Gmail应用程序实现了这样的行为。

11.2。例

下面的描述包含用于实现撤消操作的一个例子。它使用动画来自动淘汰撤销按钮了一段时间后。在这个例子中创建一个名为新项目com.vogella.android.userinterface.undo基础上,BlankTemplate模板。为您的布局如下活动。它使用
的FrameLayout
显示用户接口的两个不同的部分。按钮栏最初是隐藏的。按钮采用了绘制。无论是添加这样的绘制到项目或删除引用。
<FrameLayoutxmlns: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"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><ListViewandroid:id="@+id/listview"android:layout_width="match_parent"android:layout_height="match_parent"></ListView></RelativeLayout><LinearLayoutandroid:id="@+id/undobar"android:visibility="gone"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="bottom|center_horizontal"android:layout_margin="20dp"android:alpha="100"android:background="#808080"android:dividerPadding="11dp"android:padding="4dp"><TextViewandroid:id="@+id/undobar_message"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Deleted"android:textAppearance="?android:attr/textAppearanceMedium"android:textColor="#fff"/><Buttonandroid:id="@+id/undobar_button"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="30dp"android:onClick="onClick"android:background="#808080"android:drawableLeft="@drawable/ic_undobar_undo"android:text="Undo"android:textAppearance="?android:attr/textAppearanceMedium"android:textColor="#fff"/></LinearLayout中></的FrameLayout>
改变你的活动,使其类似于下面的代码。在Eclipse中的Android项目向导已经生成的
动作条
条目。本条目中使用以下代码。如有疑问,创建自己的
动作条
条目。
如果您选择的入门动作条,按钮栏变为显示5秒钟。

12.性能优化

下面将实施适配器从前面的例子性能优化的版本。创建以下
MyPerformanceArrayAdapter
类。
在您使用新的适配器的活动。如果你运行的应用程序应该看起来是一样的,但它会快很多,尤其是对于大型数据集。

13教程:如何显示在ListView两个项目

可以使用
SimpleAdapter
类显示两种元素的数据。此类期望字符串的一个阵列(
数据),其中输入数据的字段定义。它还要求整数的数组定义为以这些字段映射行布局部件的ID。实际的数据是再映射的列表。地图定义了从数据的值的每个字段。以下示出了重用来自机器人的预定义布局的行的一个例子。

14.选择在ListView多个项目

14.1。模型和ListView互动

经常,你需要选择你的项目
的ListView
。由于排
的ListView
越来越回收你不能存储在选择
视图
的水平。选择只是一种可能的例子,但你可以imange你行和模型之间的相互作用等。坚持你必须与选定的状态更新数据模型的选择。更新您的数据模型
的ListView
你定义自己的
适配器
类。在这个适配器类附加一个监听到
视图
负责选择模型元素。如果您选择更新,你可以作为一个标签添加到视图来访问它的模型的状态。下面的例子演示了如何使用标准的Java对象,如何从交互
视图
和模型。

14.2。教程:域模型和交互行

继续使用
de.vogella.android.listactivity
项目。创建以下
模型
如果该元素是当前选择哪个保持的名称和信息。
创建一个名为以下新布局文件
rowbuttonlayout.xml
创建以下
适配器
。此适配器加上了一个侦听器
复选框
观点。如果该复选框被选中的模式的基础数据被改变。
复选框
获取经由所分配的相应的模型元素
getTag()
方法。
最后,您更改活动以下内容。
如果你开始你的应用程序,你应该能够标志的物品。这些变化将反映在您的模型。

15.实现可扩展的ListView

15.1。ExpandableListView

ExpandableListView
类似
的ListView
但允许您定义组和详细信息该组。
ExpandableListView
预期和类型的适配器
BaseExpandableListAdapter
。在这种情况下,你必须定义两个布局,一个组,另一个用于详情一行。

15.2。ExpandableListView例如

在下面的例子中,你创建一个类似于下面的截图可扩展列表视图。创建了一个名为com.vogella.android.listview.expandable与所谓的活动
MainActivity
。创建或调整下列布局文件。一是
布局/activity_main.xml
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/LinearLayout1"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context=".MainActivity"><ExpandableListViewandroid:id="@+id/listView"android:layout_width="match_parent"android:layout_height="wrap_content"></ExpandableListView></LinearLayout中>
随后创建
布局/listrow_group.xml
<CheckedTextViewxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/textView1"android:layout_width="wrap_content"android:layout_height="?android:attr/listPreferredItemHeight"android:layout_marginLeft="8dp"android:drawableRight="@drawable/ic_launcher"android:gravity="left"android:paddingLeft="32dp"android:paddingTop="8dp"android:text="Test"android:textSize="14sp"android:textAlignment="textEnd"android:textStyle="bold"/>
最后所需的布局
布局/listrow_details.xml
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="40dp"android:clickable="true"android:orientation="vertical"android:paddingLeft="40dp"tools:context=".MainActivity"><TextViewandroid:id="@+id/textView1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:drawableLeft="@drawable/ic_launcher"android:drawablePadding="5dp"android:gravity="center_vertical"android:text="@string/hello_world"android:textSize="14sp"android:textStyle="bold"></TextView><Viewandroid:layout_width="match_parent"android:layout_height="1dp"android:background="@android:color/black"/></LinearLayout中>
创建占据着为你的域模型下面的类
ExpandableListView
最后创建适配器所描述的以下列表并改变活动下面提供的代码。

16.教程:杂项

16.1。添加longclick监听器列表项

您还可以添加
LongItemClickListener
视图
。对于这个接收
的ListView
经由
getListVIew()
方法,并设置
LongItemClickListener
经由setOnItemLongClickListener()方法。

16.2。页眉和页脚

当然,你可以把任意
查看
你周围的ListView元素。例如,你可以定义两个布局
TextViews
ListView控件
之间。在这种情况下,两个TextViews总是会名单(头)以上可见,另一个是下面的ListView可见。如果你只想在显示列表页眉或页脚列表中看到您可以使用该列表的开头或结尾
addHeaderView()
方法或
addFooterView()
上的方法
的ListView
类。

17.SimpleCursorAdapter

如果你与内容供应商合作,或直接与数据库可以使用
SimpleCursorAdapter
定义数据为您
的ListView
。下面将演示如何访问联系人ContentProvider的。创建一个名为“de.vogella.android.listactivity.cursor”与新的Android项目活动称为MyListActivity。改变
MyListActivity
下面的内容。
请确保你给你的应用程序读取联系人的权限。(在AndroidManifest.xml中使用权限“android.permission.READ_CONTACTS”)

18.其他开源库

有时不得不按下动作条的刷新按钮来刷新数据,可恼人的用户。克里斯·巴内斯实施了一个开放源码库来实现拉刷新模式的
列表视图
。https://github.com/chrisbanes/Android-PullToRefresh。你也可能需要使用的刷卡解雇的姿态,从一个ListView删除项目。罗马Nurik提供在一个这样的例子Android的刷卡到解雇库而杰克沃顿回迁到早期的Android版​​本在SwipeToDismissNOA。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: