ListView 绝对可以称得上是 Android 中最常用的控件之一,几乎所有的应用程序都会用到它。
当我们的程序中有大量的数据需要展示的时候,就可以借助 ListView 来实现。
下面以水果展示程序为例介绍。
1. 在活动布局文件中加入ListView控件
修改activity_main.xml中的代码,例子如下
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
></ListView>
</LinearLayout>
2. 定制ListView界面
2.1 为子项指定数据存储基类
定义一个实体类,作为ListView适配器的适配类型。
新建类Fruit,用来存储子项的数据,代码如下所示。
public class Fruit{
private String name;
private String imageId;
public Fruit(String name, int imageId){
this.name = name;
this.imageId = imageId;
}
public String getName(){
return this.name;
}
public int getImageId(){
return this.imageId;
}
}
Fruit类中有2个字段,name表示水果的名字,imageId表示水果对应图片的资源ID。
2.2 为子项指定自定义布局
在layout目录下新建fruit_item.xml,代码如下所示。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<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="10dip" />
</LinearLayout>
在这个布局中,ImageView用于显示水果的图片,TextView用于显示水果的名称。
2.3 为ListView指定数据适配器
创建一个继承自ArrayAdapter的适配器,将泛型指定为Fruit类。
新建类FruitAdapter,代码如下所示。
public class FruitAdapter extends ArrayAdapter<Fruit>{
private int resourceId;
public FruitAdapter(Context context, int textViewResourceId, List<Fruit> objects){
super(context, textViewResourceId, objects);
this.resourceId = textViewResourceId;
}
@Override
public View getView(int position, View convertView, ViewGroup parent){
Fruit fruit = getItem(position);
View view;
ViewHolder viewHolder;
if(convertView == null){
view = LayoutInflater.from(getContext()).inflate(this.resourceId, null);
viewHolder = new ViewHolder();
viewHolder.fruitImage = (ImageView)view.findViewById(R.id.fruit_image);
viewHolder.fruitName = (ImageView)view.findViewById(R.id.fruit_name);
view.setTag(viewHolder); //将viewHolder存储在view中
} else{
view = convertView;
viewHolder = (ViewHolder)view.getTag(); //重新获取ViewHolder
}
viewHolder.fruitImage.setImageResource(fruit.getImageId());
viewHolder.fruitName.setImageResource(fruit.getName());
return view
}
class ViewHolder{
ImageView fruitImage;
TextView fruitName;
}
}
我们新增了一个内部类ViewHolder,用于对控件的实例进行缓存。当convertView为空时,创建一个ViewHolder对象,并将控件的实例都存放在ViewHolder里,然后调用View的setTag()方法,将ViewHolder对象存储在View里。当convertView不为空时则调用View的getTag()方法,把ViewHolder重新取出。这样所有控件的实例都缓存在ViewHolder里,这样就不用每次都把布局重新加载一遍,也不用每次都通过findeViewById()方法来获取控件实例了。
3.在活动中为ListView绑定数据及点击事件
修改MainActivity中的代码,如下所示。
public class MainActivity extends Activity{
private List<fruit> fruitList = new ArrayList<Fruit>();
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.id.activity_main);
initFruits(); //实例化数据
FruitAdapter adapter = new FruitAdapter(MainActivity.this, R.layout.fruit_item, fruitList);
ListView listView = (ListView)findViewById(R.id.list_view);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Fruit fruit = fruitList.get(position);
Toast.makeText(MainActivity.this, fruit.getName(),
Toast.LENGTH_SHORT).show();
}
});
}
private void initFruits() {
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);
}
}
可以看到,我们使用了
setOnItemClickListener()
方法来为
ListView
注册了一个监听器,当用户点击了
ListView
中的任何一个子项时就会回调
onItemClick()
方法,在这个方法中可以通过
position
参数判断出用户点击的是哪一个子项,然后获取到相应的水果,并通过
Toast
将水果的名字显示出来。
重新运行程序,并点击一下西瓜,效果如下图
所示。