一、項目布局
在Eclipse中,建立一個新的Android項目,使用預設的Activity和main.xml布局檔案。在main.xml檔案中,聲明一個ListView控制項。
main.xml檔案:
1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout
3 xmlns:android=http://schemas.android.com/apk/res/android
4 android:orientation="vertical"
5 android:layout_width="fill_parent"
6 android:layout_height="fill_parent"
7 android:background="#FFFFFF">
8
9 <ListView
10 android:id="@+id/listView1"
11 android:layout_width="fill_parent"
12 android:layout_height="fill_parent" />
13 </LinearLayout>
上面的代碼,使用了簡單的線性布局方式,內部垂直排列。聲明了一個ListView,佔據整個父容器,他的android.layout_width和android.layout_width的屬性都為fill_parent。ListView有一個唯一的id:listView1,在MainActivity中將用來引用ListView控制項。
為了建立定製的header,先在你的工程中建立一個新的xml布局檔案:listview_header_row.xml,在裡面聲明一個TextView控制項,屬性值見下面的代碼。將會建立出一個白色字型,藍色背景的header。
1 listview_header_row.xml檔案:
2 <?xml version="1.0" encoding="utf-8"?>
3 <LinearLayout
4 xmlns:android="http://schemas.android.com/apk/res/android"
5 android:orientation="horizontal"
6 android:layout_width="fill_parent"
7 android:layout_height="fill_parent">
8
9 <TextView android:id="@+id/txtHeader"
10 android:layout_width="fill_parent"
11 android:layout_height="fill_parent"
12 android:gravity="center_vertical"
13 android:layout_alignParentTop="true"
14 android:layout_alignParentBottom="true"
15 android:textStyle="bold"
16 android:textSize="22dp"
17 android:textColor="#FFFFFF"
18 android:padding="10dp"
19 android:text="Weather Photos"
20 android:background="#336699" />
21
22 </LinearLayout>
為了建立定製的ListView的行樣式,先在你的工程中建立另一個xml布局檔案:listview_item_row.xml。Android 會將這個檔案的內容傳遞給每個ListView的item,你將可以自由的聲明任何你想添加進裡面的控制項。本文中,我使用了一個ImageView來顯示天氣表徵圖和一個TextView來顯示該條item的主題。下面是listview_item_row.xml檔案的代碼:
1 listview_item_row.xml檔案:
2 <?xml version="1.0" encoding="utf-8"?>
3 <LinearLayout
4 xmlns:android="http://schemas.android.com/apk/res/android"
5 android:orientation="horizontal"
6 android:layout_width="fill_parent"
7 android:layout_height="fill_parent"
8 android:padding="10dp">
9
10 <ImageView android:id="@+id/imgIcon"
11 android:layout_width="wrap_content"
12 android:layout_height="fill_parent"
13 android:gravity="center_vertical"
14 android:layout_alignParentTop="true"
15 android:layout_alignParentBottom="true"
16 android:layout_marginRight="15dp"
17 android:layout_marginTop="5dp"
18 android:layout_marginBottom="5dp" />
19
20 <TextView android:id="@+id/txtTitle"
21 android:layout_width="fill_parent"
22 android:layout_height="fill_parent"
23 android:gravity="center_vertical"
24 android:layout_alignParentTop="true"
25 android:layout_alignParentBottom="true"
26 android:textStyle="bold"
27 android:textSize="22dp"
28 android:textColor="#000000"
29 android:layout_marginTop="5dp"
30 android:layout_marginBottom="5dp" />
31
32 </LinearLayout>
本文中,我下載了一些32 X 32像素的PNG格式的表徵圖。如果你願意,你也可以使用你自己的表徵圖。準備好你的表徵圖,放到你工程的drawable-mdpi檔案目錄下。接下來,在工程中建立一個java類,命名為Weather.java,這個類將用於建立一個定製的ArrayAdapter來綁定對象到ListView中。下面是Weather.java檔案的代碼,它有兩個簡單的屬性icon和title,一個普通的建構函式用於初始化屬性。
二、項目程式開發
為了方便大家理解,我將程式結構流程畫出來:
圖3. 重要對象關係結構
1 Weather.java檔案:
2 public class Weather {
3 public int icon;
4 public String title;
5 public Weather(){
6 super();
7 }
8
9 public Weather(int icon, String title) {
10 super();
11 this.icon = icon;
12 this.title = title;
13 }
14 }
注意,上面listview_item_row.xml檔案有兩個View,對應於Weather類的兩個屬性。Weather類的屬性值將被顯示到這兩個View中。為了將這兩個View串連起來,你需要建立一個定製的ArrayAdapter,它繼承了Android的ArrayAdapter類,並重寫了getView方法。添加一個新的java類到你的工程中,命名為WeatherAdapter,具體的實現代碼如下:
1 WeatherAdapter.java檔案:
2 public class WeatherAdapter extends ArrayAdapter<Weather>{
3
4 Context context;
5 int layoutResourceId;
6 Weather data[] = null;
7
8 public WeatherAdapter(Context context, int layoutResourceId, Weather[] data) {
9 super(context, layoutResourceId, data);
10 this.layoutResourceId = layoutResourceId;
11 this.context = context;
12 this.data = data;
13 }
14
15 @Override
16 public View getView(int position, View convertView, ViewGroup parent) {
17 View row = convertView;
18 WeatherHolder holder = null;
19
20 if(row == null)
21 {
22 LayoutInflater inflater = ((Activity)context).getLayoutInflater();
23 row = inflater.inflate(layoutResourceId, parent, false);
24
25 holder = new WeatherHolder();
26 holder.imgIcon = (ImageView)row.findViewById(R.id.imgIcon);
27 holder.txtTitle = (TextView)row.findViewById(R.id.txtTitle);
28
29 row.setTag(holder);
30 }
31 else
32 {
33 holder = (WeatherHolder)row.getTag();
34 }
35
36 Weather weather = data[position];
37 holder.txtTitle.setText(weather.title);
38 holder.imgIcon.setImageResource(weather.icon);
39
40 return row;
41 }
42
43 static class WeatherHolder
44 {
45 ImageView imgIcon;
46 TextView txtTitle;
47 }
48 }
在上面的代碼中,第一個比較重要的是類的建構函式有三個參數,第一個參數是Context對象(我們可以傳遞當前使用WeatherAdapter類的activity對象的引用,即MainActivity.this對象);第二個參數是resource的id(它是我們想用來呈現每個ListView的item的布局檔案的id),在本文中我將傳遞我建立的listview_item_row.xml布局檔案的id;第三個參數是一個Weather對象的數組,用於為Adapter適配器提供顯示資料的資料來源。
ArrayAdapter的getView方法被重寫了。這個方法將被ListView每個 item項調用來建立視圖View,它們的屬性是我們設定的。getView方法也使用了一個臨時的holder類(在WeatherAdapter類內部聲明的內部類),這個類將被用於緩衝ImageView和TextView,以便它們能夠被ListView中的每行重用,這也會為我們帶來巨大的效能的提升,由於我們不斷地訪問兩個相同的views(ImageView和TextView)的屬性,我們不必為每個ListView的Item尋找這兩個控制項。上面的代碼也是用了Android內建的LayoutInflator來解析xml布局檔案(用於動態載入xml布局檔案,以便能夠尋找其中的內容)。
最後一點代碼是我們應用的MainActivity。裡面,我們使用了所有上面聲明的對象。下面是MainActivity.java檔案的代碼:
MainActivity.java檔案:
2 public class MainActivity extends Activity {
3
4 private ListView listView1;
5
6 @Override
7 public void onCreate(Bundle savedInstanceState) {
8 super.onCreate(savedInstanceState);
9 setContentView(R.layout.main);
10
11 Weather weather_data[] = new Weather[]
12 {
13 new Weather(R.drawable.weather_cloudy, "Cloudy"),
14 new Weather(R.drawable.weather_showers, "Showers"),
15 new Weather(R.drawable.weather_snow, "Snow"),
16 new Weather(R.drawable.weather_storm, "Storm"),
17 new Weather(R.drawable.weather_sunny, "Sunny")
18 };
19
20 WeatherAdapter adapter = new WeatherAdapter(this,
21 R.layout.listview_item_row, weather_data);
22
23
24 listView1 = (ListView)findViewById(R.id.listView1);
25
26 View header = (View)getLayoutInflater().inflate(R.layout.listview_header_row, null);
27 listView1.addHeaderView(header);
28
29 listView1.setAdapter(adapter);
30 }
MainActivity.java檔案中有幾個需要解釋下的地方,以便你能更好的理解。首先,我們建立了一個Weather對象的數組,icon和title被作為參數傳遞給了它的建構函式;接下來,WeatherAdapter對象被建立,listview_item_row.xml檔案的id和Weather對象數組被傳遞給了它的建構函式。再一次,我們使用了Android的LayoutInflator來解析listview_item_row.xml布局檔案。通過ListView的addHeaderView方法設定ListView的header資訊。最後,我們傳遞定製的Adapter給ListView的setAdapter方法。到現在就可以構建、運行工程了。如果一切實現正確,你會看到下面的內容。
圖2. 運行效果
最近有一段時間沒寫東西了,真是罪過啊!翻譯之中有不當之處在所難免,大家相互學習。尊重原創,尊重知識,相信分享的力量!