详解Dialog(二)——有关列表的构建
一、普通列表 普通列表的样式是这样的: 要实现这样的列表样式,是通过下面的方法来实现的: [java] view plain copy builder.setItems(CharSequence[]items,DialogInterface.OnClickListenerlistener) builder.setItems(intitemsId,DialogInterface.OnClickListenerlistener) 这两种方法实现的效果都是一样的, [java] view plain copy setItems(CharSequence[]items,DialogInterface.OnClickListenerlistener) 这个items传进去的是一个字符串数组; [java] view plain copy setItems(intitemsId,DialogInterface.OnClickListenerlistener) 这个传进去的一个itemsId,是在XML中定义好的一个字符串数组资源的ID; 下面,我们一个个看看他们的具体用法: 1、字符串数组 下面是上图是实现上图效果的代码: [java] view plain copy String[]mItems={"item0","item1","itme2","item3","itme4","item5","item6"}; AlertDialog.Builderbuilder=newAlertDialog.Builder(MyActivity.this); builder.setIcon(R.drawable.ic_launcher); builder.setTitle("使用列表字符串"); builder.setItems(mItems,newDialogInterface.OnClickListener(){ @Override publicvoidonClick(DialogInterfacedialog,intwhich){ Toast.makeText(MyActivity.this,"clicked:"+which,Toast.LENGTH_LONG).show(); } }); builder.create(); builder.show(); 可以看到首先构造一个mItems数组,然后在buidler.setItems直接传进去就好了。至于DialogInterface.OnClickListener(){}函数就是对点击事件的监听,which表示当前点击的是哪个ITEM的索引。 2、字符串资源ID 首先在xml文件夹下建一个字符串资源XML,命名为:array.xml,位置如图: 然后定义一段字符串数组: [java] view plain copy <?xmlversion="1.0"encoding="utf-8"?> <resources> <string-arrayname="dialog_items"> <item>王菲</item> <item>王力宏</item> <item>帅哥</item> <item>美女</item> </string-array> </resources> 下面就是利用SetItem来生成列表了: [java] view plain copy AlertDialog.Builderbuilder=newAlertDialog.Builder(MyActivity.this); builder.setIcon(R.drawable.ic_launcher); builder.setTitle("使用ResourceID"); builder.setItems(R.array.dialog_items,newDialogInterface.OnClickListener(){ @Override publicvoidonClick(DialogInterfacedialog,intwhich){ Toast.makeText(MyActivity.this,"clicked:"+which,Toast.LENGTH_LONG).show(); } }); builder.create(); builder.show(); 在这里的SetItems时直接将我们字符串数组的name直接设置进去,出来的效果就是这样的: 二、单选列表 单选列表的样式是这样的: 要实现单选列表,主要是通过下面四个其中之一来实现的: 方法一: [java] view plain copy setSingleChoiceItems(CharSequence[]items,intcheckedItem,DialogInterface.OnClickListenerlistener) 与上面一样,传进去一个字符串数组,和初始化时选中的ITEM,构造一个单选列表 方法二: [java] view plain copy setSingleChoiceItems(intitemsId,intcheckedItem,DialogInterface.OnClickListenerlistener) 同样,与上面的例子相同,这里传进去的是一个字符串数组的资源ID,字符串数组的构造方法与上面相同,就不再赘述 方法三: [java] view plain copy setSingleChoiceItems(ListAdapteradapter,intcheckedItem,DialogInterface.OnClickListenerlistener) 这 个方法是最难理解的方法,因为这里的ListAdapter并不能是普通的Adapter,不信你传一个Adapter,保证出来只是你自己的ITEM视 图,旁边的单选按钮却出不来,其实这里的Adapter只是重写单选按钮旁的文字的样式,并不支持所有的Adapter,这个我会在本文最后讲述。方法四: [java] view plain copy setSingleChoiceItems(Cursorcursor,intcheckedItem,StringlabelColumn,DialogInterface.OnClickListenerlistener) 这里通过传进去一个Cursor来构造对应的字符串数组,可以是数据库Cursor,也可以其它系统自带的数据Cursor,但基本上用不到,就不再讲了 好了,关于方法三,因为下面会接着讲SetAdapter的知识,所以这部分我留在最后再讲,这里先讲下方法一和方法二: 方法一和方法二,与上例没什么区别,下面我就以方法一以例来讲讲上面的效果图是怎么实现的吧: 代码如下: [java] view plain copy String[]mItems={"攻","受","全能型","不告诉你"}; AlertDialog.Builderbuilder=newAlertDialog.Builder(MyActivity.this); builder.setIcon(R.drawable.ic_launcher); builder.setTitle("你懂的"); builder.setSingleChoiceItems(mItems,0,newDialogInterface.OnClickListener(){ @Override publicvoidonClick(DialogInterfacedialog,intwhich){ //TODOAuto-generatedmethodstub Toast.makeText(MyActivity.this,"clicked:"+which,Toast.LENGTH_LONG).show(); } }); builder.create(); builder.show(); 很简单,构造一个mItems的String字符串,然后直接传进去setSingleChoiceItems中,默认选中第一个,即索引是0的项。 三、多选列表 先看看效果图: 自带的多选构造函数有如下几个: 方法一: [java] view plain copy setMultiChoiceItems(CharSequence[]items,boolean[]checkedItems,DialogInterface.OnMultiChoiceClickListenerlistener) 一样,传进去一个ITEMS数组和对应的项目的选中与否状态的数组; 方法二: [java] view plain copy setMultiChoiceItems(intitemsId,boolean[]checkedItems,DialogInterface.OnMultiChoiceClickListenerlistener) 这里传进去的是一个字符串数组,与第一部分相同 方法三: [java] view plain copy setMultiChoiceItems(Cursorcursor,StringisCheckedColumn,StringlabelColumn,DialogInterface.OnMultiChoiceClickListenerlistener) 同样,这里传进去的是一个CURSOR,可以是数据库的指针,也可以是系统自带数据的指针,基本不怎么用,就不讲了 下面以方法一为例看看多选列表的构造过程: [java] view plain copy String[]mItems={"经常犯二","傻叉一枚","逗逼","小清纯","沉稳大叔","有时可爱"}; AlertDialog.Builderbuilder=newAlertDialog.Builder(MyActivity.this); builder.setIcon(R.drawable.ic_launcher); builder.setTitle("性格类型"); builder.setMultiChoiceItems(mItems, newboolean[]{false,false,false,false,false,false,false}, newDialogInterface.OnMultiChoiceClickListener(){ @Override publicvoidonClick(DialogInterfacedialog,intwhich,booleanisChecked){ Toast.makeText(MyActivity.this,"clicked:"+which,Toast.LENGTH_LONG).show(); } } ); builder.show(); 这里构造了两个数组,一个是字符串数组,另一个每项对应是否选中的boolean数组 [java] view plain copy String[]mItems={"经常犯二","傻叉一枚","逗逼","小清纯","沉稳大叔","有时可爱"}; 对应的选中项的布尔值数组: [java] view plain copy newboolean[]{false,false,false,false,false,false,false} 四、自定义列表项 这节我带大家自定义列表项的实现,故名思义,就是每个ITEM都是我们自己来定义,使用我们自己的Adapter,先看看效果: 要实现自定义列表主要是造下面这个函数来实现的: [java] view plain copy setAdapter(ListAdapteradapter,DialogInterface.OnClickListenerlistener) 直接将我们构造好的Adapter设置进去。 下面就带大家实现下图示中的视图: 1、构造Adapter 有关派生自BaseAdapter来构造ListViewAdapter的过程就不再细讲了,大家可以参考我以前的两篇文章: 1、《List控件使用---SimpleAdapter使用详解(一)》 2、《BaseAdapter——convertView回收机制与动态控件响应》 第 一篇现在看来着实太烂了,一直想重写又没时间来做,大家可以再搜搜网上的其它相关文章来学一下有关BaseAdapter的相关内容吧。第二篇有关 convertView的回收机制写的还是挺不错的,大家可以仔细看看,相信会对ListView的机制有一个更清晰的理解。废话不多说了,下面言转正 转,看看我们这里的ListAdapter的构造过程: 首先是单个Item的布局:(list_item.xml) 很简单,采用水平布局,左边一个图像,右边一个对应的TEXT,这里只是基本实现功能,大家完全可以在理解这篇文章的基础上派生出更复杂的视图 [java] view plain copy <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="match_parent"> <ImageView android:id="@+id/item_imageview" android:layout_width="80dip" android:layout_height="80dip" android:scaleType="fitCenter"/> <TextView android:id="@+id/item_text" android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center_vertical|left" android:textSize="20sp"/> </LinearLayout> 对应的视图类: [java] view plain copy privateclassViewHolder{ publicTextViewmTvTitle; publicImageViewmImageView; } 其中有两个变量,一个存储对应的TextView,另一个存储对应的ImageView; 现在我们还需要一个类来存储视图类中TextView的标题字符串,和对应ImageView的图片资源的ID值,这就是我们的数据类: [java] view plain copy publicstaticclassDataHolder{ publicStringtitle; publicintImageID; publicDataHolder(Stringtitle,intimageID){ this.title=title; this.ImageID=imageID; } } 我们先阶段性的看看我们的ListViewAdapter: 首先是派生自BaseAdapter,然后是构造函数,我们传进去一个DataHolder的列表,用来存储每个Item应该显示的内容 [java] view plain copy publicclassListItemAdapterextendsBaseAdapter{ privateList<DataHolder>mDataList=newArrayList<DataHolder>(); privateLayoutInflatermInflater; publicListItemAdapter(Contextcontext,ArrayList<DataHolder>datalist){ if(datalist!=null&&datalist.size()>0){ mDataList.addAll(datalist); } mInflater=LayoutInflater.from(context); } ……………… } 然后是最关键的getView部分: [java] view plain copy publicViewgetView(intposition,ViewconvertView,ViewGroupviewGroup){ ViewHolderholder=null; if(convertView==null){ holder=newViewHolder(); convertView=mInflater.inflate(R.layout.list_item,null); holder.mTvTitle=(TextView)convertView.findViewById(R.id.item_text); holder.mImageView=(ImageView)convertView.findViewById(R.id.item_imageview); convertView.setTag(holder); }else{ holder=(ViewHolder)convertView.getTag(); } holder.mImageView.setImageResource(mDataList.get(position).ImageID); holder.mTvTitle.setText(mDataList.get(position).title); returnconvertView; } 首先是通过covertView的tag来获取重复利用的convertView,这什么要这么写,看《BaseAdapter——convertView回收机制与动态控件响应》 然后是利用传进来的数据,初始化列表Item: [java] view plain copy holder.mImageView.setImageResource(mDataList.get(position).ImageID); holder.mTvTitle.setText(mDataList.get(position).title); 最后返回convertView,让系统去做绘图 到这里ListViewAdapter的构造过程就基本完成了,下面是完整的代码: [java] view plain copy /** *Createdbyharvic *date2015-1-11 **/ publicclassListItemAdapterextendsBaseAdapter{ privateList<DataHolder>mDataList=newArrayList<DataHolder>(); privateLayoutInflatermInflater; publicListItemAdapter(Contextcontext,ArrayList<DataHolder>datalist){ if(datalist!=null&&datalist.size()>0){ mDataList.addAll(datalist); } mInflater=LayoutInflater.from(context); } @Override publicintgetCount(){ returnmDataList.size(); } @Override publicObjectgetItem(intposition){ returnmDataList.get(position); } @Override publiclonggetItemId(intposition){ returnposition; } @Override publicViewgetView(intposition,ViewconvertView,ViewGroupviewGroup){ ViewHolderholder=null; if(convertView==null){ holder=newViewHolder(); convertView=mInflater.inflate(R.layout.list_item,null); holder.mTvTitle=(TextView)convertView.findViewById(R.id.item_text); holder.mImageView=(ImageView)convertView.findViewById(R.id.item_imageview); convertView.setTag(holder); }else{ holder=(ViewHolder)convertView.getTag(); } holder.mImageView.setImageResource(mDataList.get(position).ImageID); holder.mTvTitle.setText(mDataList.get(position).title); returnconvertView; } privateclassViewHolder{ publicTextViewmTvTitle; publicImageViewmImageView; } publicstaticclassDataHolder{ publicStringtitle; publicintImageID; publicDataHolder(Stringtitle,intimageID){ this.title=title; this.ImageID=imageID; } } } 2、构造列表 在MainActivity中,首先是初始化我们的ListViewAdapter,要初始化Adapter,就要首先传进去一个DataHolder的数组,所有要先构造一个DataHolder的数组 [java] view plain copy privateArrayList<ListItemAdapter.DataHolder>initDataHolder(){ ArrayList<ListItemAdapter.DataHolder>datalist=newArrayList<ListItemAdapter.DataHolder>(); ListItemAdapter.DataHolderdata_1=newListItemAdapter.DataHolder("可爱萌宠1",R.drawable.animal1); ListItemAdapter.DataHolderdata_2=newListItemAdapter.DataHolder("可爱萌宠2",R.drawable.animal2); ListItemAdapter.DataHolderdata_3=newListItemAdapter.DataHolder("可爱萌宠3",R.drawable.animal3); ListItemAdapter.DataHolderdata_4=newListItemAdapter.DataHolder("可爱萌宠4",R.drawable.animal4); datalist.add(data_1); datalist.add(data_2); datalist.add(data_3); datalist.add(data_4); returndatalist; } 在构造完成数据列表之后,下面就是构造我们的自定义的列表了,我把整个对话框显示过程整合成了一个函数createCustomList,代码如下: [java] view plain copy privatevoidcreateCustomList(){ ArrayList<ListItemAdapter.DataHolder>dataHolders=initDataHolder(); ListItemAdapteradapter=newListItemAdapter(MyActivity.this,dataHolders); AlertDialog.Builderbuilder=newAlertDialog.Builder(MyActivity.this); builder.setIcon(R.drawable.ic_launcher); builder.setTitle("可爱萌宠"); builder.setAdapter(adapter,newDialogInterface.OnClickListener(){ @Override publicvoidonClick(DialogInterfacedialogInterface,intwhich){ Toast.makeText(MyActivity.this,"clicked:"+which,Toast.LENGTH_LONG).show(); } }); builder.create(); builder.show(); } OK啦,到这,整个自列表项的内容就讲完了,下面再回过来给大家说说上面我们提到的有关单选列表自定义Adapter的问题。 五、有关单选列表自定义Adapter 这里主要讲的函数是第二部分单选列表中的方法三: [java] view plain copy setSingleChoiceItems(ListAdapteradapter,intcheckedItem,DialogInterface.OnClickListenerlistener) 在第四部分,我们构造了一个ListAdapter,这里需要的也是同样的一个ListAdapter,那我们直接将第四部分中的Adapter传进去,会是什么效果呢? 也就是利用下面的代码: 我们直接在createCustomList()上面改一下,即把builder.setAdapter()直接换成setSingleChoiceItems() ,传进去Adpter,看看在我们定义的视图后面会不会出现一个单选按钮呢? [java] view plain copy privatevoidcreateCustomList(){ ArrayList<ListItemAdapter.DataHolder>dataHolders=initDataHolder(); ListItemAdapteradapter=newListItemAdapter(MyActivity.this,dataHolders); AlertDialog.Builderbuilder=newAlertDialog.Builder(MyActivity.this); builder.setIcon(R.drawable.ic_launcher); builder.setTitle("可爱萌宠"); builder.setSingleChoiceItems(adapter,0,newDialogInterface.OnClickListener(){ @Override publicvoidonClick(DialogInterfacedialogInterface,intwhich){ Toast.makeText(MyActivity.this,"clicked:"+which,Toast.LENGTH_LONG).show(); } }); builder.create(); builder.show(); } 运行一下,效果是这样的: 看见了没,毛也没有,坑爹玩意,那这个函数到底是用来做什么的呢,在源码中有这样一个文件: 地址在:$android_sdk_home/platforms/Android-x.x/data/res/layout/simple_list_item_single_choice.xml 文件内容是这样的: [html] view plain copy <CheckedTextViewxmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/single_list_item" android:layout_width="match_parent" android:layout_height="?android:attr/listPreferredItemHeightSmall" android:textAppearance="?android:attr/textAppearanceListItemSmall" android:gravity="center_vertical" android:checkMark="?android:attr/listChoiceIndicatorSingle" android:paddingStart="?android:attr/listPreferredItemPaddingStart" android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" /> 利用这个玩意是可以实现效果的,我们来试一下。 1、新建Adapter 新建一个布局文件,来保存ListVIew的每项的Item,代码如下: [html] view plain copy <CheckedTextViewxmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/single_list_item" android:layout_width="match_parent" android:layout_height="?android:attr/listPreferredItemHeightSmall" android:textAppearance="?android:attr/textAppearanceListItemSmall" android:gravity="center_vertical" android:checkMark="?android:attr/listChoiceIndicatorSingle" android:paddingStart="?android:attr/listPreferredItemPaddingStart" android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" /> 在Adapter中,同样,用来保存ITEM视图的ViewHolder类,如下: [java] view plain copy privateclassViewHolder{ publicTextViewmName; } 因 为在布局中只有一个TextView,所以在ViewHolder中也只需要一个TextView与其对应,至于类似上面的承载对应数据的 DataHolder,因为我们只需要一个String字符串数组就足够了,所以就没必要再新建一个类来承载这些数据了,所以我们要构造Adapter 时,传进来一个字符串数组就好了: 所以简单的构造函数为: 在构造时,传进来我们每项要显示的标题的字符串数组String[] items,并将其直接添加到我们的List<String> mList中。 [java] view plain copy publicclassSingleChoiceAdapterextendsBaseAdapter{ privateLayoutInflatermInflater; privateList<String>mList=newArrayList<String>(); publicSingleChoiceAdapter(Contextcontext,String[]items){ mInflater=LayoutInflater.from(context); if(items==null||items.length<=0){ return; } for(Stringitem:items){ mList.add(item); } } ………… } 然后是最关键的getView()部分: [java] view plain copy publicViewgetView(intposition,ViewconvertView,ViewGroupviewGroup){ ViewHolderholder=null; if(convertView==null){ holder=newViewHolder(); convertView=mInflater.inflate(R.layout.single_choice_item,null); holder.mName=(TextView)convertView.findViewById(R.id.single_list_item); convertView.setTag(holder); }else{ holder=(ViewHolder)convertView.getTag(); } holder.mName.setText(mList.get(position)); returnconvertView; } 这段代码难度不大,就是每次绘图时,将TextView的内容设置为我们指定的字符串: [java] view plain copy holder.mName.setText(mList.get(position)); 下面是SingleChoiceAdapter完整的代码: [java] view plain copy /** *Createdbyharvic *date2015-1-11 */ publicclassSingleChoiceAdapterextendsBaseAdapter{ privateLayoutInflatermInflater; privateList<String>mList=newArrayList<String>(); publicSingleChoiceAdapter(Contextcontext,String[]items){ mInflater=LayoutInflater.from(context); if(items==null||items.length<=0){ return; } for(Stringitem:items){ mList.add(item); } } @Override publicintgetCount(){ returnmList.size(); } @Override publicObjectgetItem(intposition){ returnmList.get(position); } @Override publiclonggetItemId(intposition){ returnposition; } @Override publicViewgetView(intposition,ViewconvertView,ViewGroupviewGroup){ ViewHolderholder=null; if(convertView==null){ holder=newViewHolder(); convertView=mInflater.inflate(R.layout.single_choice_item,null); holder.mName=(TextView)convertView.findViewById(R.id.single_list_item); convertView.setTag(holder); }else{ holder=(ViewHolder)convertView.getTag(); } holder.mName.setText(mList.get(position)); returnconvertView; } privateclassViewHolder{ publicTextViewmName; } } 然后就是使用的阶段了 2、构造单选列表 这里首先构造SingleChoiceAdapter的实例,然后将其传入setSingleChoiceItems中,代码如下: [java] view plain copy String[]mItems={"攻","受","全能型","不告诉你"}; SingleChoiceAdapteradapter=newSingleChoiceAdapter(MyActivity.this,mItems); AlertDialog.Builderbuilder=newAlertDialog.Builder(MyActivity.this); builder.setIcon(R.drawable.ic_launcher); builder.setTitle("可爱萌宠"); builder.setSingleChoiceItems(adapter,0,newDialogInterface.OnClickListener(){ @Override publicvoidonClick(DialogInterfacedialogInterface,intwhich){ Toast.makeText(MyActivity.this,"clicked:"+which,Toast.LENGTH_LONG).show(); } }); builder.create(); builder.show(); 运行出来的效果如图: 看到没,这里效果是出来了,可见,在单选按钮中,定义Adapter并不是随便定义的,只能定义CheckedTextView的视图,其它是不支持的!!!! 好了,到这里本篇就结束了,下篇给大家讲讲有关自定义对话框的内容。 本文转自农夫山泉别墅博客园博客,原文链接:http://www.cnblogs.com/yaowen/p/5434828.html,如需转载请自行联系原作者