ListView的高級使用


ListView在android開放中用的比較多,所以接下來就進行ListView的使用的講解。

首先創建一個android項目,項目名爲ListViewTest.

ListView的簡單使用

修改佈局文件,修改後代碼如下:

  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.      >  
  6.   
  7.     <ListView   
  8.         android:id="@+id/list_view"  
  9.         android:layout_width="match_parent"  
  10.         android:layout_height="match_parent"  
  11.         ></ListView>  
  12.   
  13. </LinearLayout>  


修改MainActivity的代碼:

  1. package com.wj.listviewtest;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.view.Menu;  
  6. import android.widget.ArrayAdapter;  
  7. import android.widget.ListView;  
  8.   
  9. public class MainActivity extends Activity {  
  10.   
  11.     private String [] data={"apple","banana","orange",  
  12.             "watermelon","pear","grape","pineapple","strawberry",  
  13.             "cherry","mango"};  
  14.     @Override  
  15.     protected void onCreate(Bundle savedInstanceState) {  
  16.         super.onCreate(savedInstanceState);  
  17.         setContentView(R.layout.activity_main);  
  18.         //創建適配器  
  19.         ArrayAdapter<String> adapter=new ArrayAdapter<String>(  
  20.                 MainActivity.this,android.R.layout.simple_list_item_1,  
  21.                 data);  
  22.         ListView listView=(ListView) findViewById(R.id.list_view);  
  23.         listView.setAdapter(adapter);  
  24.     }  
  25.   
  26.     @Override  
  27.     public boolean onCreateOptionsMenu(Menu menu) {  
  28.         // Inflate the menu; this adds items to the action bar if it is present.  
  29.         getMenuInflater().inflate(R.menu.main, menu);  
  30.         return true;  
  31.     }  
  32.   
  33. }  


運行程序結果如下:



ListView是用於顯示大量數據的,這些數據我們可以事先準備好,也可以從網上或者數據中中讀取。

android.R.layout.simple_list_item_1是作爲ListView子項佈局的id,這是android內置的佈局文件裏面只有一個TextView,可用於簡單地顯示一段文本。


2.定製ListView的界面

首先準備一組圖片,分別對應上面提供的水果。

接着定義一個實體類,作爲ListView適配器的適配類型,新建Fruit類,代碼如下:

  1. package com.wj.listviewtest;  
  2.   
  3. public class Fruit {  
  4.   
  5.     private String name;//水果名  
  6.     private int imageId;//水果圖片的資源id  
  7.       
  8.     //無參構造函數  
  9.     public Fruit(){}  
  10.     //有參構造函數  
  11.     public Fruit(String name,int imageId){  
  12.         this.name=name;  
  13.         this.imageId=imageId;  
  14.     }  
  15.       
  16.     public String getName() {  
  17.         return name;  
  18.     }  
  19.     public void setName(String name) {  
  20.         this.name = name;  
  21.     }  
  22.     public int getImageId() {  
  23.         return imageId;  
  24.     }  
  25.     public void setImageId(int imageId) {  
  26.         this.imageId = imageId;  
  27.     }  
  28.       
  29. }  

Fruit類中只有2個字段,name表示水果的名字,imageId表示水果對應圖片的資源id,然後需要爲ListView的子項指定一個我們自定義的佈局,在layout目錄下面新建fruit_item.xml代碼如下:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     >  
  6.     <ImageView   
  7.         android:id="@+id/fruit_image"  
  8.         android:layout_width="wrap_content"  
  9.         android:layout_height="wrap_content"  
  10.         />  
  11.   
  12.     <TextView   
  13.         android:id="@+id/fruit_name"  
  14.         android:layout_width="wrap_content"  
  15.         android:layout_height="wrap_content"  
  16.         android:layout_gravity="center"  
  17.         android:layout_marginLeft="10dip"  
  18.         />  
  19.       
  20. </LinearLayout>  


這個佈局中我們定義了一個ImageView用於顯示水果的圖片,又定義了一個TextView用於顯示水果的名稱。

接着我們要創建一個自定義的適配器,這個適配器繼承自ArrayAdapter,並將泛型指定爲Fruit。新建一個類FruitAdapter代碼如下:

  1. package com.wj.listviewtest;  
  2.   
  3. import java.util.List;  
  4.   
  5. import android.content.Context;  
  6. import android.view.LayoutInflater;  
  7. import android.view.View;  
  8. import android.view.ViewGroup;  
  9. import android.widget.ArrayAdapter;  
  10. import android.widget.ImageView;  
  11. import android.widget.TextView;  
  12.   
  13. public class FruitAdapter extends ArrayAdapter<Fruit> {  
  14.   
  15.     private int resourceId;  
  16.     public FruitAdapter(Context context, int textViewResourceId,  
  17.             List<Fruit> objects) {  
  18.         super(context, textViewResourceId, objects);  
  19.         // TODO Auto-generated constructor stub  
  20.         /* 
  21.          * 重寫了父類的構造函數,用於將上下文,ListView子項佈局的id和數據都傳進來。 
  22.          * */  
  23.         resourceId=textViewResourceId;  
  24.     }  
  25.     @Override  
  26.     public View getView(int position, View convertView, ViewGroup parent) {  
  27.         // TODO Auto-generated method stub  
  28.         //return super.getView(position, convertView, parent);  
  29.         /* 
  30.          * 重寫getView方法,這個方法在每個子項被滾動到屏幕內的時候會被調用,在getView方法中 
  31.          * ,首先通過getItem方法得到當前項的Fruit實例,然後使用LayoutInflater來爲這個子項加載 
  32.          * 我們傳入的佈局,接着調用View的findViewById方法分別獲取到ImageView和TextView的實例, 
  33.          * 並分別調用他們的setImageResource和setText方法來設置顯示的圖片和文字,最後返回佈局 
  34.          * */  
  35.         Fruit fruit=getItem(position);//獲取當前項的Fruit實例  
  36.         //初始話ListView的子項佈局  
  37.         View view=LayoutInflater.from(getContext()).inflate(resourceId, null);  
  38.         ImageView fruitImage=(ImageView) view.findViewById(R.id.fruit_image);  
  39.         TextView fruitName=(TextView) view.findViewById(R.id.fruit_name);  
  40.         fruitImage.setImageResource(fruit.getImageId());  
  41.         fruitName.setText(fruit.getName());  
  42.         return view;  
  43.     }  
  44.       
  45.       
  46.       
  47.   
  48. }  

修改MainActivity的代碼如下:

  1. package com.wj.listviewtest;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import android.app.Activity;  
  7. import android.os.Bundle;  
  8. import android.view.Menu;  
  9. import android.widget.ArrayAdapter;  
  10. import android.widget.ListView;  
  11.   
  12. public class MainActivity extends Activity {  
  13.   
  14.     /*private String [] data={"apple","banana","orange", 
  15.             "watermelon","pear","grape","pineapple","strawberry", 
  16.             "cherry","mango"};*/  
  17.     private List<Fruit> fruitList=new ArrayList<Fruit>();  
  18.     @Override  
  19.     protected void onCreate(Bundle savedInstanceState) {  
  20.         super.onCreate(savedInstanceState);  
  21.         setContentView(R.layout.activity_main);  
  22.         /*//創建適配器 
  23.         ArrayAdapter<String> adapter=new ArrayAdapter<String>( 
  24.                 MainActivity.this,android.R.layout.simple_list_item_1, 
  25.                 data); 
  26.         ListView listView=(ListView) findViewById(R.id.list_view); 
  27.         listView.setAdapter(adapter);*/  
  28.         initFruits();//初始化水果  
  29.         FruitAdapter adapter=new FruitAdapter(MainActivity.this,  
  30.                 R.layout.fruit_item, fruitList);  
  31.         ListView listView=(ListView) findViewById(R.id.list_view);  
  32.         //設置適配器  
  33.         listView.setAdapter(adapter);  
  34.           
  35.     }  
  36.   
  37.     @Override  
  38.     public boolean onCreateOptionsMenu(Menu menu) {  
  39.         // Inflate the menu; this adds items to the action bar if it is present.  
  40.         getMenuInflater().inflate(R.menu.main, menu);  
  41.         return true;  
  42.     }  
  43.       
  44.     public void initFruits(){  
  45.         Fruit apple=new Fruit("apple",R.drawable.apple_pic);  
  46.         fruitList.add(apple);  
  47.         Fruit banana=new Fruit("banana",R.drawable.banana_pic);  
  48.         fruitList.add(banana);  
  49.         Fruit orange=new Fruit("orange",R.drawable.orange_pic);  
  50.         fruitList.add(orange);  
  51.         Fruit watermelon=new Fruit("watermelon",R.drawable.watermelon_pic);  
  52.         fruitList.add(watermelon);  
  53.         Fruit pear=new Fruit("pear",R.drawable.pear_pic);  
  54.         fruitList.add(pear);  
  55.         Fruit grape=new Fruit("grape",R.drawable.grape_pic);  
  56.         fruitList.add(grape);  
  57.         Fruit pineapple=new Fruit("pineapple",R.drawable.pineapple_pic);  
  58.         fruitList.add(pineapple);  
  59.         Fruit strawberry=new Fruit("strawberry",R.drawable.strawberry_pic);  
  60.         fruitList.add(strawberry);  
  61.         Fruit cherry=new Fruit("cherry",R.drawable.cherry_pic);  
  62.         fruitList.add(cherry);  
  63.         Fruit mango=new Fruit("mango",R.drawable.mango_pic);  
  64.         fruitList.add(mango);  
  65.     }  
  66.       
  67.       
  68.   
  69. }  

運行程序,結果如下:



這是一個簡單的界面,不過更加複雜的界面也可以通過修改fruit_item.xml文件來實現更加複雜的ListView。



下面我們來提示下ListView的運行效率。

目前我們的ListView的運行效率是很低的,因爲在FruitAdapter的getView方法中每次都要將佈局重寫加載了一遍,當ListView快速滾動的時候這就會成爲性能的瓶頸。仔細觀察,getView方法中還有一個convertView參數,這個參數用於將之前加載好的佈局進行緩存,以便之後可以進行重用,修改FruitAdapter中的代碼,帶入如下所示:

  1. @Override  
  2.     public View getView(int position, View convertView, ViewGroup parent) {  
  3.         // TODO Auto-generated method stub  
  4.         //return super.getView(position, convertView, parent);  
  5.         /* 
  6.          * 重寫getView方法,這個方法在每個子項被滾動到屏幕內的時候會被調用,在getView方法中 
  7.          * ,首先通過getItem方法得到當前項的Fruit實例,然後使用LayoutInflater來爲這個子項加載 
  8.          * 我們傳入的佈局,接着調用View的findViewById方法分別獲取到ImageView和TextView的實例, 
  9.          * 並分別調用他們的setImageResource和setText方法來設置顯示的圖片和文字,最後返回佈局 
  10.          * */  
  11.         Fruit fruit=getItem(position);//獲取當前項的Fruit實例  
  12.         View view;  
  13.         /* 
  14.          * 在getView()方法中進行判斷,如果convertView爲空,則使用LayoutInflater去加載佈局, 
  15.          * 如果不爲空,則直接對convertView進行重用。這樣可以大大提升ListView的效率,在快速滾動的時候 
  16.          * 也可以表現更好的性能。 
  17.          * */  
  18.         if(convertView==null){  
  19.             //初始話ListView的子項佈局  
  20.             view=LayoutInflater.from(getContext()).inflate(resourceId, null);  
  21.         }else{  
  22.             view=convertView;  
  23.         }  
  24.         /*//初始話ListView的子項佈局 
  25.         View view=LayoutInflater.from(getContext()).inflate(resourceId, null);*/  
  26.         ImageView fruitImage=(ImageView) view.findViewById(R.id.fruit_image);  
  27.         TextView fruitName=(TextView) view.findViewById(R.id.fruit_name);  
  28.         fruitImage.setImageResource(fruit.getImageId());  
  29.         fruitName.setText(fruit.getName());  
  30.         return view;  
  31.     }  

上面的代碼進行了部分的優化,雖然現在已經不用在重複的去加載佈局了,但是每次在getView方法中還是會調用View的view.findViewById()方法來獲取一次控件的實例。我們可以藉助一個ViewHolder來對這部分性能進行優化,修改FruitAdapter中的代碼,如下所示:

  1. package com.wj.listviewtest;  
  2.   
  3. import java.util.List;  
  4.   
  5. import android.content.Context;  
  6. import android.view.LayoutInflater;  
  7. import android.view.View;  
  8. import android.view.ViewGroup;  
  9. import android.widget.ArrayAdapter;  
  10. import android.widget.ImageView;  
  11. import android.widget.TextView;  
  12.   
  13. public class FruitAdapter extends ArrayAdapter<Fruit> {  
  14.   
  15.     private int resourceId;  
  16.     public FruitAdapter(Context context, int textViewResourceId,  
  17.             List<Fruit> objects) {  
  18.         super(context, textViewResourceId, objects);  
  19.         // TODO Auto-generated constructor stub  
  20.         /* 
  21.          * 重寫了父類的構造函數,用於將上下文,ListView子項佈局的id和數據都傳進來。 
  22.          * */  
  23.         resourceId=textViewResourceId;  
  24.     }  
  25.     @Override  
  26.     public View getView(int position, View convertView, ViewGroup parent) {  
  27.         // TODO Auto-generated method stub  
  28.         //return super.getView(position, convertView, parent);  
  29.         /* 
  30.          * 重寫getView方法,這個方法在每個子項被滾動到屏幕內的時候會被調用,在getView方法中 
  31.          * ,首先通過getItem方法得到當前項的Fruit實例,然後使用LayoutInflater來爲這個子項加載 
  32.          * 我們傳入的佈局,接着調用View的findViewById方法分別獲取到ImageView和TextView的實例, 
  33.          * 並分別調用他們的setImageResource和setText方法來設置顯示的圖片和文字,最後返回佈局 
  34.          * */  
  35.         Fruit fruit=getItem(position);//獲取當前項的Fruit實例  
  36.         View view;  
  37.         ViewHolder viewHolder;  
  38.         /* 
  39.          * 在getView()方法中進行判斷,如果convertView爲空,則使用LayoutInflater去加載佈局, 
  40.          * 如果不爲空,則直接對convertView進行重用。這樣可以大大提升ListView的效率,在快速滾動的時候 
  41.          * 也可以表現更好的性能。 
  42.          * */  
  43.         if(convertView==null){  
  44.             //初始話ListView的子項佈局  
  45.             view=LayoutInflater.from(getContext()).inflate(resourceId, null);  
  46.             viewHolder=new ViewHolder();  
  47.             viewHolder.fruitImage=(ImageView) view.findViewById(R.id.fruit_image);  
  48.             viewHolder.fruitName=(TextView) view.findViewById(R.id.fruit_name);  
  49.             view.setTag(viewHolder);//將ViewHolder存儲在View中  
  50.         }else{  
  51.             view=convertView;  
  52.             viewHolder=(ViewHolder) view.getTag();//重新獲取ViewHolder  
  53.         }  
  54.         /*//初始話ListView的子項佈局 
  55.         View view=LayoutInflater.from(getContext()).inflate(resourceId, null);*/  
  56.         /*ImageView fruitImage=(ImageView) view.findViewById(R.id.fruit_image); 
  57.         TextView fruitName=(TextView) view.findViewById(R.id.fruit_name);*/  
  58.         viewHolder.fruitImage.setImageResource(fruit.getImageId());  
  59.         viewHolder.fruitName.setText(fruit.getName());  
  60.         return view;  
  61.     }  
  62.       
  63.       
  64.     class ViewHolder{  
  65.         ImageView fruitImage;  
  66.         TextView  fruitName;  
  67.     }  
  68.   
  69. }  

通過上面兩步優化後,ListView的運行效率已經不錯了。


ListView的點擊事件

修改代碼如下:

  1. package com.wj.listviewtest;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import android.app.Activity;  
  7. import android.os.Bundle;  
  8. import android.view.Menu;  
  9. import android.view.View;  
  10. import android.widget.AdapterView;  
  11. import android.widget.AdapterView.OnItemClickListener;  
  12. import android.widget.ArrayAdapter;  
  13. import android.widget.ListView;  
  14. import android.widget.Toast;  
  15.   
  16. public class MainActivity extends Activity {  
  17.   
  18.     /*private String [] data={"apple","banana","orange", 
  19.             "watermelon","pear","grape","pineapple","strawberry", 
  20.             "cherry","mango"};*/  
  21.     private List<Fruit> fruitList=new ArrayList<Fruit>();  
  22.     @Override  
  23.     protected void onCreate(Bundle savedInstanceState) {  
  24.         super.onCreate(savedInstanceState);  
  25.         setContentView(R.layout.activity_main);  
  26.         /*//創建適配器 
  27.         ArrayAdapter<String> adapter=new ArrayAdapter<String>( 
  28.                 MainActivity.this,android.R.layout.simple_list_item_1, 
  29.                 data); 
  30.         ListView listView=(ListView) findViewById(R.id.list_view); 
  31.         listView.setAdapter(adapter);*/  
  32.         initFruits();//初始化水果  
  33.         FruitAdapter adapter=new FruitAdapter(MainActivity.this,  
  34.                 R.layout.fruit_item, fruitList);  
  35.         ListView listView=(ListView) findViewById(R.id.list_view);  
  36.         //設置適配器  
  37.         listView.setAdapter(adapter);  
  38.         /* 
  39.          * setOnItemClickListener()方法來爲ListView註冊一個監聽器,當用戶點擊了ListView 
  40.          * 中的任何一個子項時就會回調nItemClick()方法,在這個方法中可以通過position參數判斷出用戶點擊 
  41.          * 的是哪一個子項,然後獲取相應的水果,並通過Toast將水果的名字顯示出來。 
  42.          * */  
  43.         listView.setOnItemClickListener(new OnItemClickListener(){  
  44.   
  45.             @Override  
  46.             public void onItemClick(AdapterView<?> parent, View view, int position,  
  47.                     long id) {  
  48.                 // TODO Auto-generated method stub  
  49.                 Fruit fruit=fruitList.get(position);  
  50.                 Toast.makeText(MainActivity.this,   
  51.                         fruit.getName(), Toast.LENGTH_SHORT).show();  
  52.                   
  53.             }  
  54.               
  55.         });  
  56.     }  
  57.   
  58.     @Override  
  59.     public boolean onCreateOptionsMenu(Menu menu) {  
  60.         // Inflate the menu; this adds items to the action bar if it is present.  
  61.         getMenuInflater().inflate(R.menu.main, menu);  
  62.         return true;  
  63.     }  
  64.       
  65.     public void initFruits(){  
  66.         Fruit apple=new Fruit("apple",R.drawable.apple_pic);  
  67.         fruitList.add(apple);  
  68.         Fruit banana=new Fruit("banana",R.drawable.banana_pic);  
  69.         fruitList.add(banana);  
  70.         Fruit orange=new Fruit("orange",R.drawable.orange_pic);  
  71.         fruitList.add(orange);  
  72.         Fruit watermelon=new Fruit("watermelon",R.drawable.watermelon_pic);  
  73.         fruitList.add(watermelon);  
  74.         Fruit pear=new Fruit("pear",R.drawable.pear_pic);  
  75.         fruitList.add(pear);  
  76.         Fruit grape=new Fruit("grape",R.drawable.grape_pic);  
  77.         fruitList.add(grape);  
  78.         Fruit pineapple=new Fruit("pineapple",R.drawable.pineapple_pic);  
  79.         fruitList.add(pineapple);  
  80.         Fruit strawberry=new Fruit("strawberry",R.drawable.strawberry_pic);  
  81.         fruitList.add(strawberry);  
  82.         Fruit cherry=new Fruit("cherry",R.drawable.cherry_pic);  
  83.         fruitList.add(cherry);  
  84.         Fruit mango=new Fruit("mango",R.drawable.mango_pic);  
  85.         fruitList.add(mango);  
  86.     }  




  87. 本文轉載自 http://blog.csdn.net/j903829182/article/details/40683293 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章