Listview 排序是在 Android 开发中应用最广泛的功能之一。在 ListView 中,所有的东西都是基于一系列数据来构建的,因此一旦你有足够的数据要处理,就要开始考虑如何排序。
ListView 排序的过程相对简单,但是需要了解一些关于排序算法和 ListView 自身的知识。本篇文章将详细介绍如何利用 ListView 实现数据排序功能。
一、简要介绍 ListView
ListView 是 Android 开发中最基本的UI控件之一,它是一种可继承的基础控件,可以展示出大数据集,其内部实现使用Adapter来对数据进行适配,并且ListView能够支持用户的滑动操作。
二、ListView 的数据适配
在介绍 ListView 排序功能之前,我们首先来介绍一个关于 ListView 的数据适配问题,因为 ListView 排序功能本质上就是在排序数据后重新适配 ListView。
ListView 提供了两种方式来适配数据,即 BaseAdapter 和 ArrayAdapter。其中 ArrayAdapter 是基于一个字符串数组来适配数据,而 BaseAdapter 可以适配任意类型的数据。
BaseAdapter 适配数据需要实现以下四种方法:
1. getCount()
该方法用于获取适配器中一共有多少数据项需要被渲染
2. getItem(int position)
该方法用于获取适配器中指定位置上的数据对象
3. getItemId(int position)
该方法用于获取适配器中指定位置上的数据对象的ID,一般实现为返回列表项编号
4. getView(int position, View convertView, ViewGroup parent)
该方法用于获取适配器中指定位置对应的列表项布局
以上四个方法中,getView() 是最重要的方法,它决定了每个列表项的布局以及如何填充数据。我们还需要实现一个方法来初始化视图的 ViewHolder。
BaseAdapter 的数据适配需要有一定的技术储备,而 ArrayAdapter 的数据适配则要简单得多。我们可以通过适当的封装来实现自定义适配器。具体方法如下:
```Java
public class MyAdapter extends ArrayAdapter {
private ArrayList mDataList;
public MyAdapter(Context context, int resource, ArrayList dataList) {
super(context, resource, dataList);
mDataList = dataList;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
LayoutInflater inflater = ((Activity) getContext()).getLayoutInflater();
convertView = inflater.inflate(R.layout.list_item_layout, parent, false);
holder = new ViewHolder();
holder.name = (TextView) convertView.findViewById(R.id.name_tv);
holder.age = (TextView) convertView.findViewById(R.id.age_tv);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Data data = mDataList.get(position);
holder.name.setText(data.getName());
holder.age.setText(String.valueOf(data.getAge()));
return convertView;
}
static class ViewHolder {
TextView name;
TextView age;
}
}
```
以上代码中,我们继承了 ArrayAdapter 并重写了 getView() 方法。这里的 ViewHolder 用来缓存 ListView 中的布局,从而提高 ListView 的滑动性能。
三、ListView 排序
ListView 的排序可以分为两种:代码排序和控件排序
- 代码排序
代码排序需要对 ListView 的数据源进行排序,然后调用适配器的 notifyDataSetChanged() 方法来通知数据发生了变化,从而刷新 ListView。具体方法如下:
```Java
Collections.sort(mDataList, new Comparator() {
@Override
public int compare(Data o1, Data o2) {
// return o1.getAge() - o2.getAge();
// return o1.getName().compareTo(o2.getName());
return o2.getAge() - o1.getAge();
}
});
mAdapter.notifyDataSetChanged();
```
以上代码中,我们首先定义了一个 Comparator 接口来比较两个对象,然后利用 Collections 工具类提供的 sort() 方法来对数据进行排序,第一个参数为要排序的 List,第二个参数为实现了 Comparator 接口的比较器对象。
这个例子以年龄来排序,如果要以姓名排序,则需要将 compare() 方法改为:
```Java
return o1.getName().compareTo(o2.getName());
```
如果要从大到小排序,则需要将 compare() 方法改为:
```Java
return o2.getAge() - o1.getAge();
```
- 控件排序
控件排序与代码排序不同,它直接对 ListView 控件进行排序。这个过程可以通过控件头部的排序按钮(一般为 ImageView)来实现。
控件排序除了对数据源进行排序之外,还需要为 ListView 的头部排序按钮注册一个点击事件监听器。以下是一个示例代码:
```Java
headerView.findViewById(R.id.sort_iv).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mOrderAscending) {
((ImageView) v).setImageResource(R.drawable.ic_arrow_down);
mOrderAscending = false;
} else {
((ImageView) v).setImageResource(R.drawable.ic_arrow_up);
mOrderAscending = true;
}
sortOrder();
}
});
private void sortOrder() {
if (mOrderAscending) {
Collections.sort(mDataList, new Comparator() {
@Override
public int compare(Data o1, Data o2) {
return o1.getName().compareTo(o2.getName());
}
});
} else {
Collections.sort(mDataList, new Comparator() {
@Override
public int compare(Data o1, Data o2) {
return o2.getName().compareTo(o1.getName());
}
});
}
mAdapter.notifyDataSetChanged();
}
```
以上代码中,我们首先为头部排序按钮注册了一个点击事件监听器,然后在枚举出排序方向之后,调用 sortOrder() 方法对数据进行排序。排序的方法类似于代码排序,只是多了一个反转方向的判断。
四、总结
本篇文章讲解了如何基于 ListView 实现数据排序功能。代码排序可以通过建立图形按钮实现,提供排序参数,实现 sort() 方法完成排序。也可以通过直接使用 ListView 控件的头部按钮实现控件排序,需要使用排序按钮注册点击事件监听器,获取点击事件后,再根据当前排序的数据进行排序并调用 notifyDataSetChanged() 方法更新 ListView 的数据和布局。
当然,以上代码仅供参考,你可以结合自己的业务逻辑和需要加以修改。