上篇給大家講了Dialog的基本元素的構建方法,今天給大家說說有關列表對話框的構建。本篇講的所有列表項都是通過系統自帶的函數生成的,對於完全自定義對話框的方法,我們會在最後一篇講。
列表對話框主要有四種:普通列表、單選列表、雙選列表、自定義視圖的列表,下面我們一個個來分析。
一、普通列表
普通列表的樣式是這樣的:
要實現這樣的列表樣式,是通過下面的方法來實現的:
builder.setItems(CharSequence[] items, DialogInterface.OnClickListener listener)
builder.setItems(int itemsId, DialogInterface.OnClickListener listener)
這兩種方法實現的效果都是一樣的,
setItems(CharSequence[] items, DialogInterface.OnClickListener listener)
這個items傳進去的是一個字符串數組;
setItems(int itemsId, DialogInterface.OnClickListener listener)
這個傳進去的一個itemsId,是在XML中定義好的一個字符串數組資源的ID;
下面,我們一個個看看他們的具體用法:
1、字符串數組
下面是上圖是實現上圖效果的代碼:
String[] mItems = {"item0", "item1", "itme2", "item3", "itme4", "item5", "item6"};
AlertDialog.Builder builder = new AlertDialog.Builder(MyActivity.this);
builder.setIcon(R.drawable.ic_launcher);
builder.setTitle("使用列表字符串");
builder.setItems(mItems, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
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,位置如圖:
然後定義一段字符串數組:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="dialog_items">
<item>王菲</item>
<item>王力宏</item>
<item>帥哥</item>
<item>美女</item>
</string-array>
</resources>
下面就是利用SetItem來生成列表了:
AlertDialog.Builder builder = new AlertDialog.Builder(MyActivity.this);
builder.setIcon(R.drawable.ic_launcher);
builder.setTitle("使用Resource ID");
builder.setItems(R.array.dialog_items, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MyActivity.this, "clicked:" + which, Toast.LENGTH_LONG).show();
}
});
builder.create();
builder.show();
在這裏的SetItems時直接將我們字符串數組的name直接設置進去,出來的效果就是這樣的:
二、單選列表
單選列表的樣式是這樣的:
要實現單選列表,主要是通過下面四個其中之一來實現的:
方法一:
setSingleChoiceItems(CharSequence[] items, int checkedItem, DialogInterface.OnClickListener listener)
與上面一樣,傳進去一個字符串數組,和初始化時選中的ITEM,構造一個單選列表
方法二:
setSingleChoiceItems (int itemsId, int checkedItem, DialogInterface.OnClickListener listener)
同樣,與上面的例子相同,這裏傳進去的是一個字符串數組的資源ID,字符串數組的構造方法與上面相同,就不再贅述
方法三:
setSingleChoiceItems (ListAdapter adapter, int checkedItem, DialogInterface.OnClickListener listener)
這個方法是最難理解的方法,因爲這裏的ListAdapter並不能是普通的Adapter,不信你傳一個Adapter,保證出來只是你自己的ITEM視圖,旁邊的單選按鈕卻出不來,其實這裏的Adapter只是重寫單選按鈕旁的文字的樣式,並不支持所有的Adapter,這個我會在本文最後講述。
方法四:
setSingleChoiceItems (Cursor cursor, int checkedItem, String labelColumn, DialogInterface.OnClickListener listener)
這裏通過傳進去一個Cursor來構造對應的字符串數組,可以是數據庫Cursor,也可以其它系統自帶的數據Cursor,但基本上用不到,就不再講了
好了,關於方法三,因爲下面會接着講SetAdapter的知識,所以這部分我留在最後再講,這裏先講下方法一和方法二:
方法一和方法二,與上例沒什麼區別,下面我就以方法一以例來講講上面的效果圖是怎麼實現的吧:
代碼如下:
String[] mItems = {"攻", "受", "全能型", "不告訴你"};
AlertDialog.Builder builder = new AlertDialog.Builder(MyActivity.this);
builder.setIcon(R.drawable.ic_launcher);
builder.setTitle("你懂的");
builder.setSingleChoiceItems(mItems, 0, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
Toast.makeText(MyActivity.this, "clicked:" + which, Toast.LENGTH_LONG).show();
}
});
builder.create();
builder.show();
很簡單,構造一個mItems的String字符串,然後直接傳進去setSingleChoiceItems中,默認選中第一個,即索引是0的項。
三、多選列表
先看看效果圖:
自帶的多選構造函數有如下幾個:
方法一:
setMultiChoiceItems (CharSequence[] items, boolean[] checkedItems, DialogInterface.OnMultiChoiceClickListener listener)
一樣,傳進去一個ITEMS數組和對應的項目的選中與否狀態的數組;
方法二:
setMultiChoiceItems (int itemsId, boolean[] checkedItems, DialogInterface.OnMultiChoiceClickListener listener)
這裏傳進去的是一個字符串數組,與第一部分相同
方法三:
setMultiChoiceItems (Cursor cursor, String isCheckedColumn, String labelColumn, DialogInterface.OnMultiChoiceClickListener listener)
同樣,這裏傳進去的是一個CURSOR,可以是數據庫的指針,也可以是系統自帶數據的指針,基本不怎麼用,就不講了
下面以方法一爲例看看多選列表的構造過程:
String[] mItems = {"經常犯二", "傻叉一枚", "逗逼", "小清純", "沉穩大叔", "有時可愛"};
AlertDialog.Builder builder = new AlertDialog.Builder(MyActivity.this);
builder.setIcon(R.drawable.ic_launcher);
builder.setTitle("性格類型");
builder.setMultiChoiceItems(mItems,
new boolean[]{false, false, false, false, false, false, false},
new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
Toast.makeText(MyActivity.this, "clicked:" + which, Toast.LENGTH_LONG).show();
}
}
);
builder.show();
這裏構造了兩個數組,一個是字符串數組,另一個每項對應是否選中的boolean數組
String[] mItems = {"經常犯二", "傻叉一枚", "逗逼", "小清純", "沉穩大叔", "有時可愛"};
對應的選中項的布爾值數組:
new boolean[]{false, false, false, false, false, false, false}
四、自定義列表項
這節我帶大家自定義列表項的實現,故名思義,就是每個ITEM都是我們自己來定義,使用我們自己的Adapter,先看看效果:
要實現自定義列表主要是造下面這個函數來實現的:
setAdapter (ListAdapter adapter, DialogInterface.OnClickListener listener)
直接將我們構造好的Adapter設置進去。
下面就帶大家實現下圖示中的視圖:
1、構造Adapter
有關派生自BaseAdapter來構造ListViewAdapter的過程就不再細講了,大家可以參考我以前的兩篇文章:
首先是單個Item的佈局:(list_item.xml)
很簡單,採用水平佈局,左邊一個圖像,右邊一個對應的TEXT,這裏只是基本實現功能,大家完全可以在理解這篇文章的基礎上派生出更復雜的視圖
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns: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>
對應的視圖類:
private class ViewHolder{
public TextView mTvTitle;
public ImageView mImageView;
}
其中有兩個變量,一個存儲對應的TextView,另一個存儲對應的ImageView;
現在我們還需要一個類來存儲視圖類中TextView的標題字符串,和對應ImageView的圖片資源的ID值,這就是我們的數據類:
public static class DataHolder{
public String title;
public int ImageID;
public DataHolder(String title,int imageID){
this.title = title;
this.ImageID = imageID;
}
}
我們先階段性的看看我們的ListViewAdapter:
首先是派生自BaseAdapter,然後是構造函數,我們傳進去一個DataHolder的列表,用來存儲每個Item應該顯示的內容
public class ListItemAdapter extends BaseAdapter {
private List<DataHolder> mDataList = new ArrayList<DataHolder>();
private LayoutInflater mInflater;
public ListItemAdapter(Context context, ArrayList<DataHolder> datalist) {
if (datalist != null && datalist.size() > 0) {
mDataList.addAll(datalist);
}
mInflater = LayoutInflater.from(context);
}
………………
}
然後是最關鍵的getView部分:
public View getView(int position, View convertView, ViewGroup viewGroup) {
ViewHolder holder = null;
if (convertView == null) {
holder=new ViewHolder();
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);
return convertView;
}
holder.mImageView.setImageResource(mDataList.get(position).ImageID);
holder.mTvTitle.setText(mDataList.get(position).title);
最後返回convertView,讓系統去做繪圖
到這裏ListViewAdapter的構造過程就基本完成了,下面是完整的代碼:
/**
* Created by harvic
* date 2015-1-11
* */
public class ListItemAdapter extends BaseAdapter {
private List<DataHolder> mDataList = new ArrayList<DataHolder>();
private LayoutInflater mInflater;
public ListItemAdapter(Context context,ArrayList<DataHolder> datalist){
if (datalist != null && datalist.size()>0){
mDataList.addAll(datalist);
}
mInflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return mDataList.size();
}
@Override
public Object getItem(int position) {
return mDataList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup viewGroup) {
ViewHolder holder = null;
if (convertView == null) {
holder=new ViewHolder();
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);
return convertView;
}
private class ViewHolder{
public TextView mTvTitle;
public ImageView mImageView;
}
public static class DataHolder{
public String title;
public int ImageID;
public DataHolder(String title,int imageID){
this.title = title;
this.ImageID = imageID;
}
}
}
2、構造列表
在MainActivity中,首先是初始化我們的ListViewAdapter,要初始化Adapter,就要首先傳進去一個DataHolder的數組,所有要先構造一個DataHolder的數組
private ArrayList<ListItemAdapter.DataHolder> initDataHolder(){
ArrayList<ListItemAdapter.DataHolder> datalist = new ArrayList<ListItemAdapter.DataHolder>();
ListItemAdapter.DataHolder data_1 = new ListItemAdapter.DataHolder("可愛萌寵1", R.drawable.animal1);
ListItemAdapter.DataHolder data_2 = new ListItemAdapter.DataHolder("可愛萌寵2", R.drawable.animal2);
ListItemAdapter.DataHolder data_3 = new ListItemAdapter.DataHolder("可愛萌寵3", R.drawable.animal3);
ListItemAdapter.DataHolder data_4 = new ListItemAdapter.DataHolder("可愛萌寵4", R.drawable.animal4);
datalist.add(data_1);
datalist.add(data_2);
datalist.add(data_3);
datalist.add(data_4);
return datalist;
}
在構造完成數據列表之後,下面就是構造我們的自定義的列表了,我把整個對話框顯示過程整合成了一個函數createCustomList,代碼如下:
private void createCustomList() {
ArrayList<ListItemAdapter.DataHolder> dataHolders = initDataHolder();
ListItemAdapter adapter = new ListItemAdapter(MyActivity.this, dataHolders);
AlertDialog.Builder builder = new AlertDialog.Builder(MyActivity.this);
builder.setIcon(R.drawable.ic_launcher);
builder.setTitle("可愛萌寵");
builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int which) {
Toast.makeText(MyActivity.this, "clicked:" + which, Toast.LENGTH_LONG).show();
}
});
builder.create();
builder.show();
}
OK啦,到這,整個自列表項的內容就講完了,下面再回過來給大家說說上面我們提到的有關單選列表自定義Adapter的問題。
五、有關單選列表自定義Adapter
這裏主要講的函數是第二部分單選列表中的方法三:
setSingleChoiceItems (ListAdapter adapter, int checkedItem, DialogInterface.OnClickListener listener)
在第四部分,我們構造了一個ListAdapter,這裏需要的也是同樣的一個ListAdapter,那我們直接將第四部分中的Adapter傳進去,會是什麼效果呢?
也就是利用下面的代碼:
我們直接在createCustomList()上面改一下,即把builder.setAdapter()直接換成setSingleChoiceItems() ,傳進去Adpter,看看在我們定義的視圖後面會不會出現一個單選按鈕呢?
private void createCustomList() {
ArrayList<ListItemAdapter.DataHolder> dataHolders = initDataHolder();
ListItemAdapter adapter = new ListItemAdapter(MyActivity.this, dataHolders);
AlertDialog.Builder builder = new AlertDialog.Builder(MyActivity.this);
builder.setIcon(R.drawable.ic_launcher);
builder.setTitle("可愛萌寵");
builder.setSingleChoiceItems(adapter, 0,new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int which) {
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
文件內容是這樣的:
<CheckedTextView xmlns: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,代碼如下:
<CheckedTextView xmlns: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類,如下:
private class ViewHolder{
public TextView mName;
}
因爲在佈局中只有一個TextView,所以在ViewHolder中也只需要一個TextView與其對應,至於類似上面的承載對應數據的DataHolder,因爲我們只需要一個String字符串數組就足夠了,所以就沒必要再新建一個類來承載這些數據了,所以我們要構造Adapter時,傳進來一個字符串數組就好了:
所以簡單的構造函數爲:
在構造時,傳進來我們每項要顯示的標題的字符串數組String[] items,並將其直接添加到我們的List<String> mList中。
public class SingleChoiceAdapter extends BaseAdapter {
private LayoutInflater mInflater;
private List<String> mList = new ArrayList<String>();
public SingleChoiceAdapter(Context context, String[] items) {
mInflater = LayoutInflater.from(context);
if (items == null || items.length <= 0) {
return;
}
for (String item : items) {
mList.add(item);
}
}
…………
}
然後是最關鍵的getView()部分:
public View getView(int position, View convertView, ViewGroup viewGroup) {
ViewHolder holder = null;
if (convertView == null) {
holder=new ViewHolder();
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));
return convertView;
}
這段代碼難度不大,就是每次繪圖時,將TextView的內容設置爲我們指定的字符串:
holder.mName.setText(mList.get(position));
下面是SingleChoiceAdapter完整的代碼:
/**
* Created by harvic
* date 2015-1-11
*/
public class SingleChoiceAdapter extends BaseAdapter {
private LayoutInflater mInflater;
private List<String> mList = new ArrayList<String>();
public SingleChoiceAdapter(Context context,String[] items){
mInflater = LayoutInflater.from(context);
if (items == null || items.length<=0){
return;
}
for(String item:items){
mList.add(item);
}
}
@Override
public int getCount() {
return mList.size();
}
@Override
public Object getItem(int position) {
return mList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup viewGroup) {
ViewHolder holder = null;
if (convertView == null) {
holder=new ViewHolder();
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));
return convertView;
}
private class ViewHolder{
public TextView mName;
}
}
然後就是使用的階段了
2、構造單選列表
這裏首先構造SingleChoiceAdapter的實例,然後將其傳入setSingleChoiceItems中,代碼如下:
String[] mItems = {"攻", "受", "全能型", "不告訴你"};
SingleChoiceAdapter adapter = new SingleChoiceAdapter(MyActivity.this,mItems);
AlertDialog.Builder builder = new AlertDialog.Builder(MyActivity.this);
builder.setIcon(R.drawable.ic_launcher);
builder.setTitle("可愛萌寵");
builder.setSingleChoiceItems(adapter, 0, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int which) {
Toast.makeText(MyActivity.this, "clicked:" + which, Toast.LENGTH_LONG).show();
}
});
builder.create();
builder.show();
運行出來的效果如圖:
看到沒,這裏效果是出來了,可見,在單選按鈕中,定義Adapter並不是隨便定義的,只能定義CheckedTextView的視圖,其它是不支持的!!!!
好了,到這裏本篇就結束了,下篇給大家講講有關自定義對話框的內容。