ListView的高级使用


ListView在android开放中用的比较多,所以接下来就进行ListView的使用的讲解。

首先创建一个android项目,项目名为ListViewTest.

ListView的简单使用

修改布局文件,修改后代码如下:

[html]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  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的代码:

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  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类,代码如下:

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  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代码如下:

[html]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  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代码如下:

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  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的代码如下:

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  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中的代码,带入如下所示:

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  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中的代码,如下所示:

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  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的点击事件

修改代码如下:

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  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 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值