Android UI 中的 ListView列表控件的示例
当程序中有大量的数据需要展示时,就需要用到 ListView 啦。ListView 允许用户通过手指上下滑动的方式将屏幕外的数据滚动到屏幕内,同时屏幕上原有的数据则会滚动出屏幕。
1 基本用法
布局文件中加入 ListView:
<?xml version="1.0" encoding="utf-8"?>
<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"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
</LinearLayout>
这里将宽度和高度都设置为 match_parent,这样 ListView 就会占据了整个布局的空间。
活动代码:
public class MainActivity extends AppCompatActivity {
private String[] data = {"暹罗猫", "布偶猫", "折耳猫", "短毛猫", "波斯猫", "蓝猫", "森林猫", "孟买猫","缅因猫","埃及猫","伯曼猫","缅甸猫","新加坡猫","美国短尾猫","巴厘猫"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
MainActivity.this, android.R.layout.simple_list_item_1, data);
((ListView) findViewById(R.id.list)).setAdapter(adapter);
}
}
ListView 是用于展示大量数据的,这些数据可以一般是来源于服务端,实际是由具体的应用场景来决定。这里我们就使用了一个简单的 data 数组来模拟。
数组中的数据需要借助适配器来传递。Android 中提供了很多适配器的实现类,其中最好用的就是 ArrayAdapter。它可以通过泛型来指定要适配的数据类型,然后在构造函数中把要适配的数据传入即可。ArrayAdapter 有多个构造函数的重载,我们应该根据实际情况选择最合适的一种。
我们使用了 android.R.layout.simple_list_item_1作为 ListView 子项布局的 id,这是一个 Android内置的布局文件,里面只有一个 TextView,用于显示一段文本。

ListView 示例
2 定制界面
现在让 ListView 可以显示更加丰富的内容。
准备好一组图片,分别对应上面提供的每一种猫,我们要让这些猫的名称旁边都有一张图。
首先定义一个实体类,作为 ListView 适配器的适配类型:
public class Cat {
/**
* 名字
*/
private String name;
/**
* 图片 ID
*/
private int imageId;
public Cat(String name, int imageId) {
this.name = name;
this.imageId = imageId;
}
public String getName() {
return name;
}
public int getImageId() {
return imageId;
}
}
我们为 ListView 的子项建一个自定义的布局,在 layout 目录下新建 cat_item.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp" />
</LinearLayout>
在这个布局中,我们定义了一个 ImageView 用于显示猫的图片,又定义了一个 TextView 用于显示猫的名称。
接着创建一个自定义的适配器,这个适配器继承 ArrayAdapter,并将泛型指定为 Cat 类:
public class CatAdapter extends ArrayAdapter<Cat> {
private int resourceId;
public CatAdapter(Context context, int resource, List<Cat> objects) {
super(context, resource, objects);
resourceId = resource;
}
@NonNull
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Cat cat = getItem(position);//获取当前项的实例
View view = LayoutInflater.from(getContext()).inflate(resourceId, parent, false);
((ImageView) view.findViewById(R.id.image)).setImageResource(cat.getImageId());
((TextView) view.findViewById(R.id.name)).setText(cat.getName());
return view;
}
}
CatAdapter 重写了 ArrayAdapter 的一组构造函数,用于将上下文、ListView 子项布局的 id 和数据都传递进来。另外又重写了 getView() 方法,这个方法在每个子项被滚动到屏幕内时会被调用。在 getView 方法中,首先通过 getItem() 方法得到当前项的 Cat 实例,然后使用
LayoutInflater 来为这个子项加载传入的布局。inflate() 的第三个参数表示不添加父布局,因为这个 View 一旦有了父布局之后,就不能再添加到 ListView 中咯。
最后修改活动类的代码:
private List<Cat> cats = new ArrayList<>();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
CatAdapter adapter = new CatAdapter(MainActivity.this, R.layout.cat_item, cats);
((ListView) findViewById(R.id.list)).setAdapter(adapter);
}
/**
* 初始化数据
*/
private void init() {
cats.add(new Cat("暹罗猫", R.drawable.cat1));
cats.add(new Cat("布偶猫", R.drawable.cat2));
cats.add(new Cat("苏格兰折耳猫", R.drawable.cat3));
cats.add(new Cat("英国短毛猫", R.drawable.cat4));
cats.add(new Cat("波斯猫", R.drawable.cat5));
cats.add(new Cat("俄罗斯蓝猫", R.drawable.cat6));
cats.add(new Cat("美国短毛猫", R.drawable.cat7));
cats.add(new Cat("异国短毛猫", R.drawable.cat8));
cats.add(new Cat("挪威森林猫", R.drawable.cat9));
cats.add(new Cat("孟买猫", R.drawable.cat10));
cats.add(new Cat("缅因猫", R.drawable.cat11));
cats.add(new Cat("埃及猫", R.drawable.cat12));
}
我们在 onCreate() 方法中创建了 CatAdapter 对象,并将 CatAdapter 作为适配器传递给了ListView 。

定制 ListView 界面
3 提升运行效率
目前运行效率是很低的,有以下原因:
- 在 CatAdapter 的 getView() 方法中,每次都将布局重新加载了一遍,当 ListView 快速滚动时,就会成为性能的瓶颈。
- 每次在 getView() 方法中会调用一次 View 的 findViewById() 方法来获取一次控件的实例。
我们可以这样解决:
- getView() 方法中有一个 convertView 参数,这个参数会将之前加载好的布局进行缓存,以便之后可以进行重用。
- 新增了一个内部类 ViewHolder,缓存控件的实例。
public class CatAdapter extends ArrayAdapter<Cat> {
private int resourceId;
public CatAdapter(Context context, int resource, List<Cat> objects) {
super(context, resource, objects);
resourceId = resource;
}
@NonNull
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Cat cat = getItem(position);//获取当前项的实例
View view;
ViewHolder viewHolder;
if (convertView == null) {
view = LayoutInflater.from(getContext()).inflate(resourceId, parent, false);
viewHolder = new ViewHolder();
viewHolder.image = (ImageView) view.findViewById(R.id.image);
viewHolder.name = (TextView) view.findViewById(R.id.name);
view.setTag(viewHolder);//保存
} else {
view = convertView;
viewHolder = (ViewHolder) view.getTag();//取出
}
viewHolder.image.setImageResource(cat.getImageId());
viewHolder.name.setText(cat.getName());
return view;
}
private class ViewHolder {
ImageView image;
TextView name;
}
}
4 点击事件
我们来实践在 ListView 中响应用户的点击事件。为活动类的 onCreate 方法新增以下代码:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Cat cat = cats.get(position);
Toast.makeText(MainActivity.this, cat.getName(), Toast.LENGTH_SHORT).show();
}
});
这里为 ListView 注册了一个监听器,当用户点击了 ListView 中的任一个子项时就会回调
onItemClick() 方法,在这个方法中可以通过 position 参数判断用户点击的是哪一个子项。

点击 ListView 子项
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
相关文章
解决Android Studio 出现“Cannot resolve symbo
今天在调试的时候,Android Studio报了一个莫名其妙的错误Cannot resolve symbol'R'让人不知所措,因为这东西根本不归我管啊,怎么会出现 Cannot resolve symbol 这种错误呢?下面给大家分享Android Studio 出现“Cannot resolve symbol”解决方案,需要的朋友可以参考下2023-03-03


最新评论