Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 從心開始學Android:ListView

從心開始學Android:ListView

編輯:關於Android編程

一、ListView的簡單用法

首先創建一個項目:ListViewDemo

android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

android:id="@+id/list_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>

在xml文件中加入一個ListView,接下來在MainActivity中
publicclassMainActivityextendsActivity{

privateString[]data={"第一行","第二行","第三行","第四行","第五行","第六行"};

@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListViewlistView=(ListView)findViewById(R.id.list_view);
ArrayAdapteradapter=newArrayAdapter
(this,android.R.layout.simple_list_item_1,data);

listView.setAdapter(adapter);

}
}
首先我們應該准備ListView要顯示的數據,但是數組中的數據無法直接傳給ListView,這時我們就要借助適配器。Android中提供了很多適配器種類,這裡用的ArrayAdapter,它通過泛型來指定要適配的數據類型,,然後再構造函數中把要適配的數據加入即可,這裡的適配器需要三個參數(上下文,子布局,數據);這裡用的子布局是android源生的布局,最後調用ListView的setAdapter()方法,將適配器傳進去。

簡單總結一下,簡單的ListView大致有四步:

1) 准備數據 2)找到ListView的id 3)創建一個適配器ArrayAdapter三個參數(上下文,子布局,數據) 4)調用ListView的setAdapter()方法,將適配器傳進去

程序運行截圖 :

\

二、定制ListView的界面

只顯示一段文本的ListView太單調了,現在我們准備好一些圖片,分別對應圖片上的水果名字。

首先我們需要定義一個實體類,作為ListView適配器的適配類型,新建類Fruit:

public class Fruit {
	private String name;
	private int imageId;
	
	public Fruit(String name,int imageId){
		this.name = name;
		this.imageId = imageId;
	}
	 
	public String getName() {
		
		return name;
	}
	public int getImageId() {
		
		return imageId;
	}
}
Fruit類中只有兩個字段,name代表水果的名字,imageId代表水果的照片的ID,然後需要為我們自己的ListView寫個自定也的布局,在layout目錄下新建fruit_item.xml:


    
    <imageview android:id="@+id/fruit_image" android:layout_width="60dp" android:layout_height="60dp/>
    
    

 

這個布局中定義了一個顯示水果的名字的TextView和顯示水果照片的ImageView,接下來我們需要創建一個自定義的適配器,這個適配器繼承自ArrayAdapter,並將泛型指定為Fruit類 ,新建類FruitAdapter:

 

public class FruitAdapter extends ArrayAdapter {

	private int resourceId ;
	/**
	 * 
	 * @param context 上下文
	 * @param textViewResourceId ListView子項布局id
	 * @param objects 數據
	 */
	public FruitAdapter(Context context, int textViewResourceId, List objects) {
		super(context, textViewResourceId, objects);

		resourceId = textViewResourceId;
	}
	
	public View getView(int position ,View convertView ,ViewGroup parent){
		//獲取當前項Fruit的實例
		Fruit fruit = getItem(position);
		//給子項加載我們的布局
		View view = LayoutInflater.from(getContext()).inflate(resourceId, null);
		//找到相對應的ImageView和TextView實例
		ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
		TextView fruitName = (TextView) view.findViewById(R.id.fruit_name);
		//設置相對應的圖片和文字
		fruitImage.setImageResource(fruit.getImageId());
		fruitName.setText(fruit.getName());
		
		return view;
	}

}

FruitAdapter重寫了父類的一組構造函數,將上下文、ListView子項布局和數據都傳遞進來。又重寫了getView()方法,這個方法在每個子項被滾動到屏幕的時候都會被調用,在getView()方法方法中,首先通過getItem()獲得當前項的Fruit的實例,然後使用LayoutInflater來為這個子項加載我們傳入的布局,LayoutInflater.from(getContext())是獲取LayoutInflater實例,接著再調用View的findViewById()方法,得到想對應的ImageView和TextView的實例,並設置圖片和文字,最後將布局返回。

 

修改MainActivity的代碼:

 

public class MainActivity extends Activity {

	private List fruitList = new ArrayList();
		
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        initFruits();//初始化數據
        
        ListView listView = (ListView) findViewById(R.id.list_view);
        FruitAdapter adapter = new FruitAdapter(this, R.layout.fruit_item, fruitList);
        
        listView.setAdapter(adapter);
               
    }

	private void initFruits() {
		
		Fruit apple = new Fruit("apple", R.drawable.apple_pic);
		fruitList.add(apple);
		//可以添加很多,這一就添加一個演示
	}
}

這裡initFruits()方法來初始化數據,程序運行顯示為

 

\

雖然現在的界面也挺簡單的,但是我們通過修改fruit_item.xml的內容,就可以修改成想要的界面了。

三、提升ListView的運行效率

目前我們的ListView的運行效率很低,因為在FruitAdapter的getView()方法中每次都將布局重新加載一遍,當ListView快速滾動的時候這就會成為性能的瓶頸,在getView()方法中有個convertView這個參數,這個參數用於將之前加載好的布局進行緩存,以後便於重用,修改FruitAdapter的代碼

public class FruitAdapter extends ArrayAdapter {

	private int resourceId ;
	/**
	 * 
	 * @param context 上下文
	 * @param textViewResourceId ListView子項布局id
	 * @param objects 數據
	 */
	public FruitAdapter(Context context, int textViewResourceId, List objects) {
		super(context, textViewResourceId, objects);

		resourceId = textViewResourceId;
	}
	
	public View getView(int position ,View convertView ,ViewGroup parent){
		//獲取當前項Fruit的實例
		Fruit fruit = getItem(position);
		//給自項加載我們的布局
		View view ;
		if (convertView == null) {
			view = LayoutInflater.from(getContext()).inflate(resourceId, null);
		} else {
			view = convertView;
		}
				
		//找到相對應的ImageView和TextView實例
		ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
		TextView fruitName = (TextView) view.findViewById(R.id.fruit_name);
		//設置相對應的圖片和文字
		fruitImage.setImageResource(fruit.getImageId());
		fruitName.setText(fruit.getName());
		
		return view;
	}

}
在getView()方法中進行判斷,如果convertView為空,就是用LayoutInflater加載布局,如果不為空view = convertView,這樣就不用重復加載布局,提高了Listview的運行效率; 雖然不用重復加載布局了,但是getView()方法中還是會調用View的FindViewById()方法來回去一次控件實例,我們借助一個ViewHolder來對這部分進行優化。

 

 

public class FruitAdapter extends ArrayAdapter {

	private int resourceId ;
	/**
	 * 
	 * @param context 上下文
	 * @param textViewResourceId ListView子項布局id
	 * @param objects 數據
	 */
	public FruitAdapter(Context context, int textViewResourceId, List objects) {
		super(context, textViewResourceId, objects);

		resourceId = textViewResourceId;
	}
	
	public View getView(int position ,View convertView ,ViewGroup parent){
		//獲取當前項Fruit的實例
		Fruit fruit = getItem(position);
		//給自項加載我們的布局
		View view ;
		ViewHolder viewHolder;
		
		if (convertView == null) {
			view = LayoutInflater.from(getContext()).inflate(resourceId, null);
			
			viewHolder = new ViewHolder();
			viewHolder.fruitImage =  (ImageView) view.findViewById(R.id.fruit_image);
			viewHolder.fruitName =  (TextView) view.findViewById(R.id.fruit_name);
			view.setTag(viewHolder);
		} else {
			view = convertView;
	
			viewHolder = (ViewHolder) view.getTag();
		}
				
	
		//設置相對應的圖片和文字
		viewHolder.fruitImage.setImageResource(fruit.getImageId());
		viewHolder.fruitName.setText(fruit.getName());
		
		return view;
	}

	class ViewHolder{
		ImageView fruitImage;
		
		TextView fruitName;
	}
}
我們新增了一個內部類ViewHolder,用於對控件的實例進行緩存,當convertView為空的時候,創建一個ViewHolder對象,並將控件的實例都存放在ViewHolder裡,然後調用View的setTag()方法,將ViewHolder對象存到View中,當convertView存在的時候,調用View的setTag()方法,把ViewHolder重新取出,這樣所有控件的實例都緩存在ViewHolde中,就沒有必要每次都通過findViewById()方法來獲取控件實例了。

注:View中的setTag(Onbect)表示給View添加一個格外的數據,以後可以用getTag()將這個數據取出來。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved