Android中ListView的使用

1、主要概念

ListView用于将大数据集以列表的形式展示。

ListView可以看成一个容器,它有如下继承链:

View <- ViewGroup <- AdapterView <- AbsListView <- ListView

可见 ListView继承自AdapterView, 而AdapterView的作用就是为ListView提供数据。
主要的API:

listView.setAdapter(adapter实例)

我们通常用的Adapter有如下几个:BaseAdapter, CursorAdapter, ArrayAdapter, SimpleAdapter.它们有如下的继承关系:

Adapter <- ListAdapter <- BaseAdapter

SimpleAdapterCursorAdapterArrayAdapter都是BaseAdapter的子类。

2、使用方法
  • Activity布局文件中加入一个ListView组件

这里entries用于指定一个数组来渲染ListView,它定义在strings.xml中,内容如下:


    
        orange
        apple
        banana
        pear
        watermelon
        lemon
        peach
        strawberry
    

到这里,运行项目已经可以看到列表项了。但这种方式只是静态的给ListView添加数据,有很大的局限性。基本不用。下面通过给ListView设置Adapter提供数据。

  • 删除上面的entries属性, 修改Activity的内容
public class ArrayAdapterActivity extends AppCompatActivity {

    private String[] items = new String[]{"monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_array_adapter);
        ListView lv = findViewById(R.id.array_adapter_list_view);
        //可以这里为ListView设置了一个Adapter
        //并且指定了一个array_adapter_list_item.xml的布局文件,因此要新建一个这样的布局文件
        //这个布局文件限制了一个数据项的显示形式,即一行数据如何展示
        //该布局文件的根标签为TextView
        //然后用上面的定义的字符串数组填充每一个TextView
        lv.setAdapter(new ArrayAdapter<>(this, R.layout.array_adapter_list_item, items));
    }
}

这样,运行程序ListView显示的便是数组中定义的值了。

  • 不同的Adapter使用方式基本一致

下面是SimpleAdapter的使用:

lv.setAdapter(new SimpleAdapter(context, data, resource, from, to));

1.context: 当前上下文

2.data: List>类型的数据集

3.resource:单个数据项的布局文件

5.from:data中map的各个key

6.to: 将key对应的值映射到数据项布局文件的某个组件
看个例子:

public class SimpleAdapterActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_simple_adapter);
        ListView lv = findViewById(R.id.simple_adapter_list_view);
        Map student1 = new HashMap<>();
        student1.put("username", "jack");
        student1.put("gender", "male");
        student1.put("age", 33);
        Map student2 = new HashMap<>();
        student2.put("username", "nacy");
        student2.put("gender", "female");
        student2.put("age", 13);
        List> students = new ArrayList<>();
        students.add(student1);
        students.add(student2);
        //from对应map的key
        String[] from = new String[]{"username", "gender", "age"};
        //to对应单行数据项布局文件中组件的id
        int[] to = new int[]{R.id.simple_adapter_username, R.id.simple_adapter_gender, R.id.simple_adapter_age};
        lv.setAdapter(new SimpleAdapter(this, students, R.layout.simple_adapter_list_item, from, to));
    }
}

单行数据项布局文件:




    

    

        

        
    

3、BaseAdapter的使用

BaseAdapter作为一个抽象类,比前几种Adapter使用起来更灵活。

下面是一个例子:

创建一个类继承BaseAdapter

public class MyBaseAdapter extends BaseAdapter {

    //根据当前上下文将一个布局文件加载到内存,实例化为对象的一个类
    private LayoutInflater layoutInflater;

    public MyBaseAdapter(Context context) {
        layoutInflater = LayoutInflater.from(context);
    }

    //决定数据项的个数
    @Override
    public int getCount() {
        return 20;
    }

    //指定位置的数据项
    @Override
    public Object getItem(int position) {
        return null;
    }

    //指定位置数据项的索引
    @Override
    public long getItemId(int position) {
        return 0;
    }

    //容纳当前数据项布局文件的一个类
    private class ViewHolder {
        public ImageView header;
        public TextView username;
    }

    //手机在滚动屏幕时,超出屏幕之外的ViewItem要被移除
    //如果有10000个ViewItem,那么getView方法就要调用10000次,加载布局文件10000次,然后创建ViewItem,这是相当耗资源的
    //为了提高性能,就需要对移除的ViewItem进行复用,每次滚动屏幕移除的ViewItem就是convertView
    //因此每次调用方法时,都要对convertView判空,如果为空才去加载布局文件,创建新的View,否则进行复用。
    //这里的ViewHolder相当于一个容器,承载了一个ViewItem中所有的组件,避免了每次都要findViewById
    //一次findViewById之后,通过setTag方法将其设置到convertView中,下次就不用再查找了
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            convertView = layoutInflater.inflate(R.layout.base_adapter_list_item, null);
            holder = new ViewHolder();
            holder.header = convertView.findViewById(R.id.iv_header);
            holder.username = convertView.findViewById(R.id.tv_username);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        holder.header.setImageResource(R.drawable.ic_launcher_foreground);
        holder.username.setText("这是第" + position + "项");
        return convertView;
    }
}

数据项布局文件:




    

    

Activity文件

public class BaseAdapterActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_base_adapter);
        ListView lv = findViewById(R.id.base_adapter_list_view);
        lv.setAdapter(new MyBaseAdapter(this));
        lv.setOnItemClickListener(new ListView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView parent, View view, int position, long id) {
                Toast.makeText(BaseAdapterActivity.this, "点击" + position, Toast.LENGTH_SHORT).show();
            }
        });

        lv.setOnItemLongClickListener(new ListView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView parent, View view, int position, long id) {
                Toast.makeText(BaseAdapterActivity.this, "长按" + position, Toast.LENGTH_SHORT).show();
                return true;
            }
        });
    }
}

你可能感兴趣的:(Android中ListView的使用)