標籤:
在安卓的資料列表顯示的時候,通常會用到ListView,所以列出下學習時候遇到的
1,用系統自訂的ListView
首先在xml檔案中建立listview
<ListView android:id="@+id/list_view" android:layout_width="match_parent" android:layout_height="match_parent" ></ListView>
然後在MainAvtivity中建立資料,此時的資料一般都是提前準備好的,一般是網上下載的或者從資料庫中提取的
這裡用數組提供一組資料,但是不能直接給ListView,這需要藉助安卓的許多適配器來進行操作(對於從資料庫來的資料用的適配器也不一樣,這裡先不管)
private String[] data = { "Apple" , "Banana" , "Orange" , "Watermelon", "Pear", "Grape", "Pineapple", "Strawberry", "Cherry", "Mango" };@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate( savedInstanceState); requestWindowFeature(Window. FEATURE_NO_TITLE); setContentView(R.layout. activity_main); ArrayAdapter<String> adapter = new ArrayAdapter<String>( MainActivity.this, android.R.layout.simple_list_item_1 , data ); ListView listview = (ListView) findViewById(R.id.list_view ); listview.setAdapter( adapter); }這裡的android.R.layout.
simple_list_item_1
是列表子項的id,這是安卓內建的布局檔案,裡面只有一個TextView,這樣就可以簡單的顯示資料使用的函數是ArrayAdapter(Context context ,
int textViewResourceId, List<T > objects) 來裝配資料 setAdapter將配置好的適配器傳進去對於適配器的問題,安卓開發手冊上介紹的主要是三種ArrayAdapter,SimpleAdapter,SimpleCursorAdapter同時還有一點要注意,Adapter與AdapterView不是同一個概念,Adapter是串連資料和AdapterView的橋樑,具體的區別可以自己度一下這樣的話,上面的代碼就完成了基本的列表功能,只是這些列表只是簡單的每項展示文字
顯然這樣的列表不能滿足要求,那麼的話就可以自己定義一個適配器來串連資料和View
2,定製ListView介面顯然上面太單調的限時不行,為此我們先建立Fruit類,儲存屬性name和imageId同時可建立一個布局檔案fruit_item.xml裡面放ImageView TextView顯示圖片和文字接著就是進行自訂的適配器,讓該適配器繼承剛才的ArrayAdapter<Fruit>具體的xml檔案建立也是很簡單
<ImageView android:id="@+id/fruit_image" android:layout_width="wrap_content" android:layout_height="wrap_content" /><TextView android:id="@+id/fruit_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginLeft="10dp" />
建立一個類,繼承適配器類
public class FruitAdapter extends ArrayAdapter<Fruit> {private int resourceId ; public FruitAdapter(Context context, int resource, List<Fruit> objects) { super( context, resource, objects); // TODO Auto-generated constructor stub resourceId= resource; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub /*return super.getView(position, convertView, parent);*/ //擷取當前的fruit執行個體 Fruit fruit= getItem( position); View view= LayoutInflater.from(getContext()).inflate(resourceId , null); ImageView fruitImage= (ImageView) view.findViewById(R.id. fruit_image); TextView fruitNmae=(TextView) view.findViewById(R.id. fruit_name); fruitImage.setImageResource( fruit.getImageId()); fruitNmae.setText( fruit.getName()); return view; }
首先是重寫了父類的一組建構函式,將上下文、ListView子項布局的id和資料都傳遞進來同時又重寫了getView方法,這個方法在每個子項被滾動到螢幕內的時候會被調用在getView方法中,先獲得當前Fruit的執行個體,然後使用LayoutInflater為子項載入傳入的布局,接著是調用findViewById()方法擷取到ImageView執行個體和TextView執行個體,然後設定文字和圖片,這樣就完成了自訂的適配器。最後就是修改MainActivity
public class MainActivity extends Activity { /*private String[] data = { "Apple", "Banana", "Orange", "Watermelon", "Pear", "Grape", "Pineapple", "Strawberry", "Cherry", "Mango" };*/private List<Fruit> fruitList = new ArrayList<Fruit>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate( savedInstanceState); /*requestWindowFeature(Window.FEATURE_NO_TITLE);*/ setContentView(R.layout. activity_main ); /*ArrayAdapter<String> adapter = new ArrayAdapter<String>( MainActivity.this, android.R.layout.simple_list_item_1, data); ListView listview = (ListView) findViewById(R.id.list_view); listview.setAdapter(adapter);*/ //初始化水果 initFruit(); FruitAdapter adapter= new FruitAdapter(MainActivity. this, R.layout.fruit_item , fruitList ); ListView listView=(ListView) findViewById(R.id.list_view ); listView.setAdapter( adapter); } private void initFruit() { // TODO Auto-generated method stub Fruit apple = new Fruit( "Apple", R.drawable.apple_pic ); fruitList.add( apple); Fruit banana = new Fruit( "Banana", R.drawable.banana_pic ); fruitList.add( banana); Fruit orange = new Fruit( "Orange", R.drawable.orange_pic ); fruitList.add( orange); Fruit watermelon = new Fruit( "Watermelon", R.drawable.watermelon_pic ); fruitList.add( watermelon); Fruit pear = new Fruit( "Pear", R.drawable. pear_pic); fruitList.add( pear); Fruit grape = new Fruit( "Grape", R.drawable.grape_pic ); fruitList.add( grape); Fruit pineapple = new Fruit( "Pineapple", R.drawable.pineapple_pic ); fruitList.add( pineapple); Fruit strawberry = new Fruit( "Strawberry", R.drawable.strawberry_pic ); fruitList.add( strawberry); Fruit cherry = new Fruit( "Cherry", R.drawable.cherry_pic ); fruitList.add( cherry); Fruit mango = new Fruit( "Mango", R.drawable.mango_pic ); fruitList.add( mango); }主要是listview完成初始化,然後產生一個自訂的適配器進行裝配資料,傳給ListView
關於效率的最佳化問題目前我們 ListView 的運行效率是很低的,因為在 FruitAdapter 的 getView()
方法中每次都將布局重新載入了一遍,當 ListView 快速滾動的時候這就會成為效能的瓶頸。
仔細觀察,getView()方法中還有一個 convertView 參數,這個參數用於將之前載入好的
布局進行緩衝, 以便之後可以進行重用
上面的操作是防止了反覆繪製布局,同時在進行每一個控制項的讀取的時候也可以防止反覆繪製的問題,具體看代碼,主要修改自訂的適配器類的一些方法
public class FruitAdapter extends ArrayAdapter<Fruit> {private int resourceId;public FruitAdapter(Context context, int resource, List<Fruit> objects) {super(context, resource, objects);// TODO Auto-generated constructor stubresourceId=resource;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {// TODO Auto-generated method stub/*return super.getView(position, convertView, parent);*///擷取當前的fruit執行個體Fruit fruit= getItem(position);/* * convertView主要是將之前載入好的布局進行緩衝 */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); }else{view =convertView;viewHolder=(ViewHolder) view.getTag();} /* ImageView fruitImage= (ImageView) view.findViewById(R.id.fruit_image);TextView fruitNmae=(TextView) view.findViewById(R.id.fruit_name);fruitImage.setImageResource(fruit.getImageId());fruitNmae.setText(fruit.getName());*/viewHolder.fruitImage.setImageResource(fruit.getImageId());viewHolder.fruitName.setText(fruit.getName());return view;}class ViewHolder{ImageView fruitImage;TextView fruitName;}}
主要是新增了一個ViewHolder類來放相應的執行個體,同時由於converView是存放布局緩衝的,所以在判斷其是否為空白的時候可以一併判斷控制項是否需要繪製
安卓入門學習之ListView