浅谈ListView

本文详细介绍了Android中ListView的使用方法,包括三种适配器的实现过程:ArrayAdapter、SimpleAdapter及BaseAdapter。并深入解析了BaseAdapter的优化技巧。

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

虽然已经有了RecyclerView,但是ListView还是有他的好处的,比较简单
如果学RecyclerView之前先学ListView会有很大的其实的,比如说ViewHolder

首先我们应该在XML的layout处写出ListView布局

<!--
android:divider="#000" 给间隔线加颜色
android:dividerHeight="10sp"  给间隔线设置高度
android:scrollbars="none"  设置右边的滚动条
none为没有
android:fadeScrollbars="false"  设置右边的滚动条(自动显示的)
-->
<!--要对ListView里面的item项做Select选择器(按下去变色)
要对整体进行设置,不能对行布局进行设置(要改变系统)
listView原来有一个系统定义好的切换的一套算法
所以把他替换要改整个listView(整体)
android:listSelector="@drawable/item_selector"用这个属性
由整个ListView做全局的处理
-->
<ListView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/listView"
    android:listSelector="@drawable/item_selector"
    />

现在ListView有三种适配器

1、数组适配器ArrayAdapter,只能显示简单是String

实现他很简单,主要是分四部

//1、获得ListView对象
ListView listView = (ListView) findViewById(R.id.listView);

//2、准备数据源
String[] data = {" * 1、获得ListView对象"
            , " * 2、准备数据源"
            , " * 3、准备适配器Adapter"
            , " * 4、将适配器关联到ListView"};

//3、准备适配器
ArrayAdapter<String> adapter = 
new ArrayAdapter<>(this
, android.R.layout.simple_list_item_1
, data);

//4、适配器关联ListView
listView.setAdapter(adapter);

第二种:简单适配器SimpleAdapter,其实也是比较简单的

实现他也是分四步:

private List<Map<String,Object>> mMapList;

//1、声明出ListView
mListView = (ListView) findViewById(R.id.listView);
//2、准备数据源
mMapList = new ArrayList<>();

Map<String , Object> map = new HashMap<>();
map.put("logo" , R.drawable.music);
map.put("title" , "千千静音");
map.put("version" , "版本:2.4.1");
map.put("size" , "大小:32.1M");
mMapList.add(map);

map = new HashMap<>();
map.put("logo" , R.drawable.calendar);
map.put("title" , "计算器");
map.put("version" , "版本:1.4.1");
map.put("size" , "大小:12.1M");
mMapList.add(map);

map = new HashMap<>();
//把这个R.drawable.Maps转换成图片是SimpleAdapter自己的事情,内部有实现
map.put("logo" , R.drawable.maps);
map.put("title" , "地图");
map.put("version" , "版本:3.5.1");
map.put("size" , "大小:35.6M");
mMapList.add(map);


map = new HashMap<>();
map.put("logo" , R.drawable.camera);
map.put("title" , "照相机");
map.put("version" , "版本:1.0.0");
map.put("size" , "大小:22.12M");
mMapList.add(map);
//3、设置适配器
SimpleAdapter simpleAdapter = 
new SimpleAdapter(this  //上下文
            ,mMapList                //数据源
            ,R.layout.item_simple_adapter         //行布局
        /**
         * Key与id要保证一一对应 必须对应相应的
         * 意思为:用logo key对应的value填入R.id.logo所对应的布局中
         */
        ,new String[]{"logo", "title" , "version" , "size"}
//键值对的key  要与键值对的key完全一样
        ,new int[]{R.id.logo , R.id.title , R.id.version , R.id.size}); //行布局中的id
//4、关联Adapter
mListView.setAdapter(simpleAdapter);

最后一种的BaseAdapter(个人觉得是最重要的),一般用来重写的

里面已经包含了优化ListView了,要仔细阅读哦

  • 首先从写BaseAdapter,继承BaseAdapter
/**
 *ListView的优化(控制次数)---》先一级后二级
 * 每次调用getView()方法都要执行两个耗时操作
 * 1、inflate方法(获得布局对象)----》》一级优化
 *    通过用convertView解决
 * 2、findViewById方法(获得控件对象)----》》二级优化
 *    通过自定义的ViewHolder解决
 * 
 *
 * 看到这个优化很容易就想起了RecyclerView的ViewHolder,现在终于知道了Viewholder的来源了吧
 */
public class MyAdapter extends BaseAdapter{
    private List<Map<String , Object>> list;   //传入的数据
    private LayoutInflater inflater;  //反射器

    public MyAdapter(Context context) {
        inflater = LayoutInflater.from(context);
    }

    public void setList(List<Map<String , Object>> list){
        this.list = list;
    }

    /**
     * 返回数据源的数量 决定了界面一共多少行
     * @return
     */
    @Override
    public int getCount() {
        return list.size();
    }

    @Override
    public Object getItem(int i) {
        return list.get(i);
    }

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

    /**
     * 自定义适配器的核心方法
     * 通过LayoutInflater反射出行布局对象,并且填充上数据内容
     * 返回一个视图  填充好布局 等着调用 每显示一行调用一次
     *
     * ConvertView的工作原理
     * 无论总量为多少,Android只渲染当前屏的item项
     * 被渲染过的Item项,它的视图对象会被保存到Recycler中
     * 新滑入屏幕的item项将从Recycler中直接获取缓存的视图,而不是再通过
     * inflate方法反射获取
     * 结论:
     * 无论总量是多少,Recycler中只需要缓存N+1个视图对象,即可保证整个ListView
     * 的显示(N为一屏幕可显示的Item数)
     * 无论总量为多少,inflate方法最多调用N+1次
     *
     * @param i
     * @param convertView 代表从缓冲区里面拿到的缓冲视图对象  一开始缓冲区里面什么都没有为null  后来有了就直接取出就可
     * @param viewGroup
     * @return
     */
    @Override
    public View getView(int i, View convertView, ViewGroup viewGroup) {

        ViewHolder holder = null;
        /**
         * 反射器:把XML的布局反射为一个view对象
         */
        if(convertView == null) {
            convertView = inflater.inflate(R.layout.item_simple_adapter, null);
            holder = new ViewHolder();
            holder.logo=   (ImageView)convertView.findViewById(R.id.logo);  
            holder.title  =(TextView)convertView.findViewById(R.id.title);
            holder.version=(TextView)convertView.findViewById(R.id.version);
            holder.size = (TextView)convertView.findViewById(R.id.size);
            //viewHolder与convertView关联起来
            convertView.setTag(holder);
        }else{
            holder = (ViewHolder) convertView.getTag();
        }


        Map<String , Object> map = list.get(i);
        holder.logo.setImageResource((Integer) map.get("logo"));
        holder.title.setText( (String)map.get("title"));
        holder.version.setText((String) map.get("version"));
        holder.size.setText((String) map.get("size"));
        return convertView;
    }


    private class ViewHolder {
        ImageView logo;
        TextView title;
        TextView version;
        TextView size;
    }
}


  • 然后使用我们从写的BaseAdapter
private List<Map<String, Object>> mMapList;

    //1、声明出ListView
    mListView = (ListView) findViewById(R.id.listView);

    //2、准备数据源
    mMapList = new ArrayList<>();
    Map<String, Object> map = new HashMap<>();
    map.put("logo", R.drawable.music);
    map.put("title", "千千静音");
    map.put("version", "版本:2.4.1");
    map.put("size", "大小:32.1M");
    mMapList.add(map);

    map = new HashMap<>();
    map.put("logo", R.drawable.calendar);
    map.put("title", "计算器");
    map.put("version", "版本:1.4.1");
    map.put("size", "大小:12.1M");
    mMapList.add(map);

    map = new HashMap<>();
    //把这个R.drawable.Maps转换成图片是SimpleAdapter自己的事情,内部有实现
    map.put("logo", R.drawable.maps);
    map.put("title", "地图");
    map.put("version", "版本:3.5.1");
    map.put("size", "大小:35.6M");
    mMapList.add(map);


    map = new HashMap<>();
    map.put("logo", R.drawable.camera);
    map.put("title", "照相机");
    map.put("version", "版本:1.0.0");
    map.put("size", "大小:22.12M");
    mMapList.add(map);


    //3、设置适配器
    MyAdapter adapter = new MyAdapter(this);
    adapter.setList(mMapList);

    //4、关联Adapter
    mListView.setAdapter(adapter);


    //5、对每一项做监听事件  不是对listView而是对里面的每一项
    //短瞬间的点击
    mListView.setOnItemClickListener(this);
    //长按
    mListView.setOnItemLongClickListener(this);

}

@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
    Toast.makeText(this , "点击item"+ i  , Toast.LENGTH_SHORT).show();
}


/**
 * 返回值
 * true 表示消化掉事件,事件不会继续传递
 * false 表示不消化事件,事件将继续传递下去
 * 结论:如果希望长按事件后,不再触发点击事件,则应将返回值设置为true
 * @param adapterView
 * @param view
 * @param i
 * @param l
 * @return
 */
@Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
    Toast.makeText(this , "长按item"+ i  , Toast.LENGTH_SHORT).show();
    return true;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值