Android中的ListView

2023-05-16

文章目录

  • 1 ListView概述
  • 2 适配器
    • 2.1 ArrayAdapter
    • 2.2 SimpleAdapter
    • 2.3 BaseAdapter

1 ListView概述

下面看一下ListView的应用场景:
在这里插入图片描述


2 适配器

先看下适配器的使用步骤:

  1. 准备布局(每一项的显示效果)
  2. 准备数据源
  3. 实例化适配器(布局+数据源)
  4. 为ListView设置适配器

2.1 ArrayAdapter

效果如下:
在这里插入图片描述
代码也十分简单:

package com.example.listviewdemo;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;

/**
 * 1.准备布局(每一项的显示效果)
 * 2.准备数据源
 * 3.实例化适配器(布局+数据源)
 * 4.为ListView设置适配器
 */
public class ArrayActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_array);

        ListView listView1 = findViewById(R.id.list_view1);

        //参数1:环境上下文(this)
        //参数2:代表数据项所应用的布局
        //参数3:数据源(数组)
        String[] data = {"AA","BB","CC","DD","EE","FF","GG","AA","BB","CC","DD","EE","FF","GG","AA","BB","CC","DD","EE","FF","GG","AA","BB","CC","DD","EE","FF","GG"};

        //使用自定义资源
        ArrayAdapter adapter = new ArrayAdapter(this,R.layout.item2,R.id.txt1,data);

        listView1.setAdapter(adapter);
    }
}

2.2 SimpleAdapter

先看下要实现的效果:
在这里插入图片描述
首先我们要自定义列表显示的layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="wrap_content">
    <ImageView
        android:id="@+id/qq_img"
        android:layout_width="50dp"
        android:layout_height="65dp"
        android:background="@mipmap/caocao"/>

    <TextView
        android:id="@+id/qq_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/qq_img"
        android:textSize="26sp"
        android:text="曹操"/>

    <TextView
        android:id="@+id/qq_mood"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/qq_img"
        android:layout_below="@id/qq_name"
        android:textColor="#00ffff"
        android:text="测试数据"/>
</RelativeLayout>

然后定义Activity对应的Layout:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".SimpleActivity">
    <ListView
        android:id="@+id/list_view2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></ListView>
</androidx.constraintlayout.widget.ConstraintLayout>

然后看下Java代码:

package com.example.listviewdemo;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class SimpleActivity extends AppCompatActivity {

    private List<Map<String,Object>> data = new ArrayList<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_simple);

        //获取ListView对象
        ListView listView2 = findViewById(R.id.list_view2);

        //实例化适配器对象
        //参数1:this
        //参数2:数据源
        initData();
        //参数3:每一项布局
        //参数4:数据来源的key数组
        String[] from = {"img","name","mood"};
        //参数5:数据去向的id数组
        int[] to = {R.id.qq_img,R.id.qq_name,R.id.qq_mood};
        //参数45对应索引上,from数组的元素代码数据源每个map的key,该key所指代的数据
        //会作为to数组对应索引上id所代表的控件的内容显示处理
        SimpleAdapter adapter = new SimpleAdapter(this,data,R.layout.item3,from,to);

        //为ListView设置适配器
        listView2.setAdapter(adapter);

        //点击事件
        listView2.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                //用Toast提示Name  Mood
                Map<String,Object> map = data.get(i);
                String name = map.get("name").toString();
                String mood = map.get("mood").toString();
                Toast.makeText(SimpleActivity.this,name+"   "+mood,Toast.LENGTH_SHORT).show();
            }
        });
    }

    public void initData(){
        //左边:头像   右上:名字   右下:心情
        Map<String,Object> map1 = new HashMap<>();
        map1.put("img",R.mipmap.caocao);
        map1.put("name","曹操");
        map1.put("mood","宁教我负天下人,休教天下人负我");

        Map<String,Object> map2 = new HashMap<>();
        map2.put("img",R.mipmap.zhenji);
        map2.put("name","甄姬");
        map2.put("mood","飘摇兮若流风之回雪,仿佛兮若轻云之蔽月");

        Map<String,Object> map3 = new HashMap<>();
        map3.put("img",R.mipmap.simayi);
        map3.put("name","司马懿");
        map3.put("mood","无奈天命之子");

        Map<String,Object> map4 = new HashMap<>();
        map4.put("img",R.mipmap.guojia);
        map4.put("name","郭嘉");
        map4.put("mood","哦");

        Map<String,Object> map5 = new HashMap<>();
        map5.put("img",R.mipmap.caocao);
        map5.put("name","曹操");
        map5.put("mood","宁教我负天下人,休教天下人负我");

        Map<String,Object> map6 = new HashMap<>();
        map6.put("img",R.mipmap.zhenji);
        map6.put("name","甄姬");
        map6.put("mood","飘摇兮若流风之回雪,仿佛兮若轻云之蔽月");

        Map<String,Object> map7 = new HashMap<>();
        map7.put("img",R.mipmap.simayi);
        map7.put("name","司马懿");
        map7.put("mood","无奈天命之子");

        Map<String,Object> map8 = new HashMap<>();
        map8.put("img",R.mipmap.guojia);
        map8.put("name","郭嘉");
        map8.put("mood","哦");


        data.add(map1);
        data.add(map2);
        data.add(map3);
        data.add(map4);
        data.add(map5);
        data.add(map6);
        data.add(map7);
        data.add(map8);
    }
}

2.3 BaseAdapter

下面先看下要实现的效果:
在这里插入图片描述
首先看下主页面的xml文件:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".BaseActivity">
    <ListView
        android:id="@+id/list_view3"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></ListView>

    <ImageView
        android:id="@+id/write"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:src="@mipmap/write"
        android:layout_gravity="right|bottom"
        android:layout_margin="40dp"/>
</FrameLayout>

然后看下item的xml文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <!--头像,昵称,发表时间(静态),发表内容,点赞,评论,转发-->
    <ImageView
        android:id="@+id/profile"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:src="@mipmap/profile1"
        android:layout_margin="5dp"/>

    <TextView
        android:id="@+id/nickname"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:text="用户1"
        android:textSize="26sp"
        android:layout_toRightOf="@id/profile"
        android:layout_marginTop="5dp"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:text="2048-10-24"
        android:textSize="22sp"
        android:layout_toRightOf="@id/profile"
        android:layout_below="@id/nickname"/>

    <TextView
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="啊,多么有意义的日子呀!!"
        android:textSize="22sp"
        android:layout_below="@id/profile"/>

    <ImageView
        android:id="@+id/repost"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:src="@mipmap/repost"
        android:layout_below="@id/content"
        android:layout_alignParentRight="true"
        android:layout_marginRight="10dp"/>

    <ImageView
        android:id="@+id/comment"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:src="@mipmap/comment"
        android:layout_below="@id/content"
       android:layout_toLeftOf="@id/repost"
        android:layout_marginRight="10dp"/>

    <ImageView
        android:id="@+id/like"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:src="@mipmap/like"
        android:layout_below="@id/content"
        android:layout_toLeftOf="@id/comment"
        android:layout_marginRight="10dp"/>
</RelativeLayout>

这里我们需要定义一个实体类,实体类如下:

package com.example.listviewdemo;

public class Msg {
    private int profile;
    private String nickname;
    private String content;
    private boolean isLike;

    public int getProfile() {
        return profile;
    }

    public void setProfile(int profile) {
        this.profile = profile;
    }

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public boolean isLike() {
        return isLike;
    }

    public void setLike(boolean like) {
        isLike = like;
    }

    public Msg(int profile, String nickname, String content, boolean isLike) {
        this.profile = profile;
        this.nickname = nickname;
        this.content = content;
        this.isLike = isLike;
    }
}

然后我们需要定义自己的Adapter类:

package com.example.listviewdemo;

import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.List;

//根据准备好的数据源和子项布局完成ListView效果的一一设置
//做出一些细节处理
public class MyAdapter extends BaseAdapter {
    private List<Msg> list;
    private Context ctx;

    public MyAdapter(List<Msg> list, Context ctx){
        this.list = list;
        this.ctx = ctx;
    }

    //获取数量(设置ListView的长度)
    @Override
    public int getCount() {
        return list.size();
    }

    //获取视图(设置ListView每一项的显示效果)--每个视图出现时都会执行
    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        //完成对view的设置
        //将布局资源转为View
        //参数1:你所要引用的布局资源
        //RecycleBin
        ViewHolder holder;
        if(view == null) {
            Log.e("TAG", "======" + i);
            //优化1:利用进入RecycleBin中的View,减少读view的赋值 (数据项看不到时相关视图就会进入RecycleBin中)
            view = LayoutInflater.from(ctx).inflate(R.layout.item4, null);
            holder = new ViewHolder();
            holder.profile = view.findViewById(R.id.profile);
            holder.nickname = view.findViewById(R.id.nickname);
            holder.content = view.findViewById(R.id.content);
            holder.like = view.findViewById(R.id.like);
            holder.comment = view.findViewById(R.id.comment);
            holder.repost = view.findViewById(R.id.repost);
            view.setTag(holder);
        }else{
            //通过getTag()取出ViewHolder对象,然后能过直接通过holder.控件的方式在外面直接操作控件
            //从而避免了大幅度使用findViewById操作
            //而事实上,getTag()本身操作效率高
            holder = (ViewHolder) view.getTag();
        }
        Msg m = list.get(i);

        //头像
//        ImageView profile = view.findViewById(R.id.profile);
        holder.profile.setImageResource(m.getProfile());

        //昵称
//        TextView nickname = view.findViewById(R.id.nickname);
        holder.nickname.setText(m.getNickname());

        //内容
//        TextView content = view.findViewById(R.id.content);
        holder.content.setText(m.getContent());

        //是否点赞
//        ImageView like = view.findViewById(R.id.like);
        if(m.isLike()){
            holder.like.setImageResource(R.mipmap.liked);
        }else{
            holder.like.setImageResource(R.mipmap.like);
        }

        //评论
//        ImageView comment = view.findViewById(R.id.comment);
        holder.comment.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(ctx,"你点击了评论",Toast.LENGTH_SHORT).show();
            }
        });
        //转发
//        ImageView repost = view.findViewById(R.id.repost);
        holder.repost.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(ctx,"--------转发----------",Toast.LENGTH_SHORT).show();
            }
        });
        return view;
    }

    //==============================================酱油方法
    //获取子项
    @Override
    public Object getItem(int i) {
        return null;
    }

    //获取子项id
    @Override
    public long getItemId(int i) {
        return 0;
    }

    //1.自定义一个类,叫做ViewHolder
    //2.将需要保存的视图声明为公开的属性
    //3.什么时候保存?当view为null时,完成对ViewHolder的实例化工作,并为各个控件属性赋值
    //4.什么时候用?  什么时候都要用(性能的提升是在view不为null时体现,滚动ListView时体现)
    //5.怎么用?当view为null时,完成了ViewHolder及内部控件属性的初始化工作后,调用一句代码
    //view.setTag(holder);
    //当view不为null时,holder = view.getTag();
    static class ViewHolder{
        public ImageView profile,like,comment,repost;
        public TextView nickname,content;
    }
}

接下来看下最后的Activity:

package com.example.listviewdemo;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;

import java.util.ArrayList;
import java.util.List;

public class BaseActivity extends AppCompatActivity {
    private ListView listView3;
    private ImageView write;
    private List<Msg> list = new ArrayList<>();
    private int[] ps = {R.mipmap.profile1,R.mipmap.profile2,
            R.mipmap.profile3,R.mipmap.profile4,R.mipmap.profile5,R.mipmap.profile6,
            R.mipmap.profile7,R.mipmap.profile8};
    private BaseAdapter adapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_base);

        listView3 = findViewById(R.id.list_view3);
        write = findViewById(R.id.write);

        initData();

        //需要传的参数:环境,数据源
        adapter = new MyAdapter(list,this);

        //设置适配器
        listView3.setAdapter(adapter);

        write.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Msg m = new Msg(R.mipmap.profile9,"paradox","这是动态新增的说说",false);
                list.add(m);
                //通知适配器更新数据
                adapter.notifyDataSetChanged();
                //设置listview自动显示到最新数据
                listView3.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
            }
        });
    }

    private void initData() {
        for(int i = 1 ; i <= 8 ; i++){
            Msg m = new Msg(ps[i-1],"用户"+i,"今天天气好晴朗,慕课处处好风光"+i,i%2==0?true:false);
            list.add(m);
        }
    }
}

我们可以看到在ListView中进行了2个优化。ViewHolder通常出现在适配器里,为的是listview滚动的时候快速设置值,而不必每次都重新创建很多对象,从而提升性能。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android中的ListView 的相关文章

随机推荐

  • ROS机器人编程学习(六)——ROS工具

    第6章 ROS工具 本章介绍了ROS的实用工具 RViz 和 rqt RViz是ROS的三维可视化工具 xff0c 便于三维视图的构建和显示 rqt是GUI开发工具 xff0c 便于图像查看 xff0c 重点介绍了rqt plot rqt
  • ZED2双目相机+IMU标定

    本文主要使用了kalibr工具标定ZED2双目相机 43 IMU xff0c 并运行VINS Fusion 阐述了标定板的选择方法 xff0c 以及标定中的注意事项 ZED2双目相机 43 IMU联合标定 1 安装标定工具2 选择标定板3
  • ZED2相机运行VINS-Fusion和ORB-SLAM3

    ZED2相机运行VINS Fusion和ORB SLAM3 1 关于zed2标定2 运行VINS Fusion3 运行ORB SLAM3 1 关于zed2标定 我最开始被zed2的标定问题折磨了好久 xff0c 用kalibr工具标定出来的
  • 用自己的设备跑各种VI-SLAM算法(1)——VINS/PL-VINS/ROVIO/MSCKF

    用自己的设备跑各种VI SLAM算法 xff08 1 xff09 1 VINS Fusion2 PL VINS3 ROVIO4 MSCKF 本人用的设备是一个海康单目相机和一个MTI惯导 xff0c 已经预先用kalibr工具标定了内外参
  • 【语言-汇编】自然常数(e)的计算

    原理介绍 它就是当 时函数 值的极限 即 xff1a 同时它也等于 计算结果 编译平台 xff1a Microsoft Visual Studio 2010 项目 xff1a Win32项目 空项目 CPU xff1a Intel R Co
  • 从零学习VINS-Mono/Fusion源代码(三):IMU预积分公式推导

    本节学习IMU预积分 xff0c 推导离散时间下的IMU预积分公式 xff0c 并解读相应代码 VINS Mono Fusion代码学习系列 xff1a 从零学习VINS Mono Fusion源代码 xff08 一 xff09 xff1a
  • 从零学习VINS-Mono/Fusion源代码(六):后端优化

    本节解析VINS后端优化 xff0c 包括优化变量 残差约束的构建 xff0c ceres求解器等 VINS Mono Fusion代码学习系列 xff1a 从零学习VINS Mono Fusion源代码 xff08 一 xff09 xff
  • TX2配置RealSense D455相机SDK和ros驱动

    TX2配置RealSense D455相机SDK和ros驱动 1 SDK安装2 RealSense ros安装3 bug及解决3 1 realsense viewer显示usb2 13 2 Could not found ddynamic
  • C++中:和::的含义与区别

    前言 xff1a 相信大多数读者和我一样在C 43 43 中总是分不清 xff1a 和 xff1a xff1a 的区别 xff0c 现在 xff0c 咱们就彻底解决它 一 1 类作用域操作符 指明了成员函数所属的类 如 xff1a M f
  • Nuttx驱动(一)简介

    第一次写Nuttx系统的驱动 xff0c 用惯了rt thread FreeRTOS等RTOS或裸机的驱动编写 写Nuttx驱动感觉好蹩脚 xff0c 顺便记录一下 xff08 by the way 先完成 xff0c 再完善 xff09
  • Nuttx驱动(二)实例

    接上一篇文章 xff0c 这篇主要是nuttx驱动编写实践部分 基础部分请移驾 Nuttx驱动 xff08 一 xff09 简介 Nuttx驱动例程 在该例程中 xff0c 假设有这么一个设备 xff1a 有3个IO输出和一个IO输入的RG
  • 【转】CAN总线学习笔记(1)- CAN基础知识

    依照瑞萨公司的 CAN入门书 的组织思路来学习CAN通信的相关知识 xff0c 并结合网上相关资料以及学习过程中的领悟整理成笔记 好记性不如烂笔头 xff0c 加油 xff01 1 CAN的一些基本概念 1 1 什么是CAN总线 CAN 是
  • git如何找回本地被覆盖的代码

    1 方法1 git reflog 查看提交记录 xff0c 找到对应的commitId git reset hard 版本号 就回到当时的那个版本 xff08 git reset hard HEAD 64 n xff09 2 git pul
  • PID入门及无人机实战

    一 PID的理论知识 大家可以搜索 PID控制算法的C语言实现 绝对的好东西 很好的入门材料 下图就是从上面摘下来的PID控制流程图 二 利用温控讲解单环PID 我们可以在电路板上焊几个电阻进行加热 xff08 PWM控制加热速度 xff0
  • 无人机姿态解算_互补滤波(1)

    一 基础知识 1 坐标系 xff1a 遵循右手定则 1 1 大地坐标系 xff08 地球坐标系 xff09 xff1a 北 xff08 x轴 xff09 东 xff08 y轴 xff09 地 xff08 z轴 xff09 xff0c 地就是
  • C++从入门到进阶的系列书籍推荐

    目录 1 C 43 43 入门书籍 1 1 C语言程序设计 xff08 谭浩强 xff09 1 2 C 43 43 Primer中文版 xff08 第5版 xff09 2 VC 43 43 MFC书籍 2 1 VC 43 43 深入详解 x
  • 无人机姿态解算_扩展卡尔曼滤波(2)

    一 扩展卡尔曼滤波 KF和EKF的公式对比 xff08 基本没差别 xff09 二 扩展卡尔曼五个公式 利用扩展卡尔曼滤波估计四元数 下图是论文中的截图 可以和前面的卡尔曼滤波估计高度文章的那五个公式对应一下 观测矩阵的确定 三 代码的实现
  • 无人机高度估计_卡尔曼滤波

    一 卡尔曼滤波公式 线性系统的离散状态空间表达式 xff1a 这是卡尔曼五个标准公式的基础 式叫做系统状态方程 xff1a xk k时刻系统状态变量值 Ak 状态转移矩阵 Bk 控制矩阵 uk 1 k 1时刻系统的输入 wk 1 k 1时刻
  • 日常记录4_pixhawk电流计的使用

    1 实物图以及连接 注意事项 接电流计的时候 xff0c 先别给电流计通电 xff0c 要先接负载 xff08 即接到飞机那一端 xff09 再给电流计供电 xff0c 不然空载的时候 xff0c 电池给电流计的电流会很大 xff0c 导致
  • Android中的ListView

    文章目录 1 ListView概述2 适配器2 1 ArrayAdapter2 2 SimpleAdapter2 3 BaseAdapter 1 ListView概述 下面看一下ListView的应用场景 xff1a 2 适配器 先看下适配