iT邦幫忙

DAY 26
1

昨天筆者拋出了一個問題:我們能不能讓 ListView 的一個 Item,不只有一個 TextView,而是包含多個 Views 呢? (例如一個 ImageView 加一個 TextView)。

答案是肯定的,為了達成這目的,我們必須做兩件事:(1) 產生 Item 的 Layout 檔;(2) 自己寫一個 Adapter。首先來看 Item 的 Layout 檔,筆者在 res/layout 下產生一個名為 listitem_baby.xml 的檔案,內容如下所示:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="6dp"
    android:paddingLeft="7dp"
    android:paddingRight="7dp"
    android:paddingTop="5dp"
    android:background="#EBEBEB" >

    <ImageView android:id="@+id/iv_headshot"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_alignParentLeft="true"
        />
    <ImageView android:id="@+id/iv_gender"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_toRightOf="@id/iv_headshot"
        android:paddingLeft="5dp"
        />
    <TextView android:id="@+id/tv_name"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:textSize="20sp"
        android:paddingLeft="5dp"
        android:layout_toRightOf="@id/iv_gender"
        />
</RelativeLayout>

這個檔案應該不需特別解說了,總而言之,我們就是讓這個 Item 包含了兩個 ImageView 和一個 TextView,接下來就要自己寫一個 Adapter 了,筆者在 src/main/java/babymanager 下建立一個 BabyArrayAdapter.java,其內容如下所示:

package lincyu.babylog.babymanager;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import java.util.ArrayList;

import lincyu.babylog.R;
import lincyu.babylog.Util;
import lincyu.babylog.db.Baby;


public class BabyArrayAdapter extends ArrayAdapter<Baby> {

	LayoutInflater inflater;
	Drawable defaultheadshot;
	
	public BabyArrayAdapter(Context context, ArrayList<Baby> babylist) {
		super(context, 0, babylist);
		inflater = LayoutInflater.from(context);
		defaultheadshot = context.getResources().getDrawable(R.drawable.defaultheadshot);
	}
	
	public void fillContent(Context mContext, ViewGroup group, Baby baby){
		
		ImageView iv_headshot = (ImageView)group.findViewById(R.id.iv_headshot);
        ImageView iv_gender = (ImageView)group.findViewById(R.id.iv_gender);
        TextView tv_name = (TextView)group.findViewById(R.id.tv_name);
        tv_name.setText(baby.toString());

        iv_headshot.setImageDrawable(defaultheadshot);
        iv_gender.setImageResource(Util.getGenderPicture(baby.gender));
	}
	
	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		RelativeLayout itemlayout = null;
		if(convertView == null) {
			itemlayout = (RelativeLayout)inflater.inflate
					(R.layout.listitem_baby, null);
		} else {
			itemlayout = (RelativeLayout) convertView;
		}
		fillContent(getContext(), itemlayout, getItem(position));
		return itemlayout;
	}
}

這個 Java 檔繼承了 ArrayAdapter<Baby>,程式 25~29 行定義了建構子,需傳入一個Context物件和一個 Baby 動態陣列,為了客製化自己的 Item,我們要覆寫 getView,44~50 行是要產生 Item 的 View 物件,首先在 27 行,我們產生一個LayoutInflater物件 [1],您可透過呼叫LayoutInfalter裡的static方法from來取得一個LayoutInflater物件,這個物件最主要的功能是把一個XML版面設計檔轉換成一個View物件,不過根據Adapter介面裡對於getView的說明 [2],我們要先判斷convertView是否是null,如果不是null,我們直接把convertView設定成我們要回傳的View,如果是null,我們才用LayoutInflater來產生要回傳的View,inflate方法需要兩個參數,第一個是「要轉換的xml檔的資源id」,第二個是要填入一個做為root的View,由於我們沒有要把這個View加到已經存在的View上面,因此填入null就可以了,由於 listitem_baby.xml 的根標籤是一個 RelativeLayout,因此在 46 行我們將 view 強制轉型成 RelativeLayout。

接著程式在 51 行呼叫 getItem 取出對應的 Baby 物件,然後在 33 ~ 35 行呼叫 findViewById 找出 RelativeLayout下的 TextView與ImageView,並將Baby 的相關資料設給TextView與ImageView。

現在回到 BabyListActivity.java,將 ArrayAdapter 改成 BabyArrayAdapter 如下所示:

// private ArrayAdapter<Baby> adapter;
private BabyArrayAdapter adapter;

// adapter = new ArrayAdapter(BabyListActivity.this,
//     R.layout.listitem,
//     R.id.tv_listitem,
//     babylist);
adapter = new BabyArrayAdapter(BabyListActivity.this, babylist);

執行結果則如下圖所示:

更多客製化 ListView 的範例與說明可參考筆者的書籍 [3]。

參考資料

[1] LayoutInflater | Android Developers, http://developer.android.com/reference/android/view/LayoutInflater.html

[2] Adapter | Android Developers, http://developer.android.com/reference/android/widget/Adapter.html

[3] 林致宇, Android程式設計入門與應用(附範例光碟), 全華出版社, ISBN: 9789572194126, http://www.opentech.com.tw/search/bookinfo.asp?isbn=9789572194126&companyID=04383129


上一篇
寶寶生活記錄 App (Day25 再探 ArrayAdapter)
下一篇
寶寶生活記錄 App (Day27 寶寶列表的其它實作細節)
系列文
以「寶寶聯絡簿」為例,適合 Android 初學者的學習筆記30

尚未有邦友留言

立即登入留言