Android查缺补漏之ListView

本文介绍了Android中ListView的相关知识。虽有RecyclerView,但ListView作为经典列表展示控件仍有价值,理解它也有助于理解RecyclerView。文中涵盖ListView的基本概念、基本用法(含不同样式及自定义布局)、自定义适配器、ViewHolder及点击事件等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上一篇“查缺补漏”总结了Toolbar的用法,这次我们来看一看ListView。

或许很多人会认为Android出了RecyclerView之后就不用再去了解ListView了,但实际上,ListView作为一种展示列表的控件,曾经在很多的APP中大量的使用,在很多场景中都是很经典的,而且理解了ListView,也会更容易理解RecyclerView。

什么是ListView

ListView是Android开发中非常重要的基础组件之一,它使得开发者能够很容易的展示一组数据。一般而言,实现一个ListView通常需要三个部分:ListView控件、Data数据、Adpter适配器,通过适配器实现将数据绑定到ListView里面的控件中。

基本用法

和其他控件一样,ListView需要先在布局文件中声明(当然特殊情况下也可以直接在Java中创建对象)
    <ListView
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></ListView>
然后在相应的Acrivity中进行绑定
mListView = (ListView)findViewById(R.id.listview);
之后,创建一些数据,这里我们需要使用ArrayList对数据进行管理
        List<Map<String, String>> datas = new ArrayList<Map<String,String>>();
        Map<String,String> map1 = new HashMap<String,String>();
        map1.put("key","item1");
        datas.add(map1);
        Map<String,String> map2 = new HashMap<String,String>();
        map2.put("key","item2");
        datas.add(map2);
创建一个SimpleAdapter将数据放到listView中
        mListView.setAdapter(new SimpleAdapter(this,datas,android.R.layout.simple_list_item_1,
                new String[]{"key"},
                new int[]{android.R.id.text1}
        ));
这样一个最基本的ListView就完成了

在上面的代码中,可以看到在创建SimpleAdapter的时候,传入了一个R.layout.simple_list_item_1的参数,这个参数用来确定item中展示的样式,除了simple_list_item_1以外,还有一些其他的样式。

样式simple_list_item_2

simple_list_item_2是一种包含副标题的样式,用法和simple_list_item_1类似,我们在设置数据的时候增加一个参数
        List<Map<String, String>> datas = new ArrayList<Map<String,String>>();
        Map<String,String> map1 = new HashMap<String,String>();
        map1.put("key1","item1");
        map1.put("key2","value1");
        datas.add(map1);
        Map<String,String> map2 = new HashMap<String,String>();
        map2.put("key1","item2");
        map2.put("key2","value1");
        datas.add(map2);
创建一个新的SimpleAdapter,设置为simple_list_item_2
        mListView.setAdapter(new SimpleAdapter(this,datas,android.R.layout.simple_list_item_2,
                new String[]{"key1","key2"},
                new int[]{android.R.id.text1,android.R.id.text2}
        ));
其中key1和key2的值分别对应android.R.id.text1和android.R.id.text2

样式simple_list_item_checked

simple_list_item_checked是一种选择的样式,用法和simple_list_item_1相似,也只需设置一个key
        mListView.setAdapter(new SimpleAdapter(this,datas,android.R.layout.simple_list_item_checked,
                new String[]{"key1"},
                new int[]{android.R.id.text1}
        ));
但是需要设置选择的模式
        /*
         * CHOICE_MODE_SINGLE  单选--ListView中只能有一个item被选中
         * CHOICE_MODE_MULTIPLE  多选--允许选中多个item
         * CHOICE_MODE_NONE  默认值,点击没反应
         */
        mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
除此之外,还有simple_list_item_multiple_choice,simple_list_item_single_choice,可以实现其他的选择样式。

自定义布局

很多时候,这些自定义布局并不能满足我们的需求,那么便需要我们自己定义item的布局。比如我们新建一个布局文件名为list_item.xml,里面放了一个高度为150dp的TextView
<?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="150dp">

    <TextView
        android:gravity="center"
        android:id="@+id/text"
        android:text="asd"
        android:layout_width="match_parent"
        android:layout_height="150dp" />
    
</LinearLayout>
然后在activity中创建SimpleAdapter
        mListView.setAdapter(new SimpleAdapter(this,datas,R.layout.list_item,
                new String[]{"key1"},
                new int[]{R.id.text}
        ));
就可以在ListView中看到我们自定义的布局

自定义适配器

虽然自定义了布局,但是在很多时候使用SimpleAdapter并不能满足我们的需求,我们可以通过自己定义适配器的方式实现我们期望的各种效果,比如我们再次实现上图的效果,创建一个继承BaseAdapter的适配器
package com.example.steveyg.listdemo;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

/**
 * Created by steveyg on 17/1/16.
 */

public class MyAdapter extends BaseAdapter{

    //数据集
    String []datas = {"item1","item2"};
    Context context;

    public MyAdapter(Context context){
        this.context = context;
    }
    @Override
    public int getCount() {
        return datas.length;
    }

    @Override
    public Object getItem(int position) {
        return datas[position];
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LayoutInflater li = LayoutInflater.from(context);
        TextView tv = (TextView) li.inflate(R.layout.list_item, null);
        tv.setText(datas[position]);
        return tv;
    }
}
在这个适配器里面重写5个方法,通过view的方式生成view进行处理,这样就可以使得item更加复杂,实现更多的效果,甚至可以返回不同的样式。而数据集datas也可以使用List的方式传入,更加的灵活。

ViewHolder

当ListView里面的数据特别多的时候,如果每次都重新创建一个View的话,会占用大量内存,对性能造成影响,因此我们需要通过重新填充的方式减少对象的创建。

图片来自网络
修改我们的Adapter
package com.example.steveyg.listdemo;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.TextView;

/**
 * Created by steveyg on 17/1/16.
 */

public class MyAdapter extends BaseAdapter {

    //数据集
    String[] datas = {"item1", "item2"};
    Context context;

    public MyAdapter(Context context) {
        this.context = context;
    }

    @Override
    public int getCount() {
        return datas.length;
    }

    @Override
    public Object getItem(int position) {
        return datas[position];
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        ViewHolder holder = null;
        if (convertView == null) {
            convertView = LinearLayout.inflate(context, R.layout.list_item, null);
            holder = new ViewHolder(convertView);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        holder.textview.setText(datas[position]);
        return convertView;
    }

    class ViewHolder {
        TextView textview;

        public ViewHolder(View view) {
            this.textview = (TextView) view.findViewById(R.id.text);
        }
    }
}
这样便实现了view holder对于adapter的优化。

点击事件

ListView的点击事件可以通过listview实现也可以通过adaper设置,如果使用了SimpleAdapter则需要通过listview实现:
        //点击事件
        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                //点击了第position个item
            }
        });

        //长按事件
        mListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
                return false;
            }
        });
而如果通过adapter设置,那么直接在getView中设置各个控件的点击事件即可。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值