安卓開發使用定製的ArrayAdapter製作ListView的Items

來源:互聯網
上載者:User

背景介紹

  對於現實世界中的商業行動裝置 App來說,Android的ListView預設的介面外觀不是非常有吸引力。它只是使用了內部的TextView控制項,在每個ListView的行(Row)裡面傳遞了一個簡單的字串而已。大多數應用,你會想要建立出富含圖形介面和呈現給使用者視覺體驗良好的應用。幸運地是,ListView 是一個非常強大的控制項,由於有可定製的item 布局的協助,它可以被定製從而輕鬆地適應你的需求。在本文中,我將向你展示怎樣建立一個定製的ListView  Item(有表徵圖,自訂的header布局)以及怎樣使用定製的ArrayAdapter將他們聯絡起來。我也會向你展示一些效能最佳化的小方法來最佳化你的ListView控制項的記憶體佔用。下面用一個例子來展示:

      圖1. 天氣圖                            圖2. 布局結構圖
 
            

   一、項目布局

  在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. 運行效果

  最近有一段時間沒寫東西了,真是罪過啊!翻譯之中有不當之處在所難免,大家相互學習。尊重原創,尊重知識,相信分享的力量!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.