25. 【Android教程】列表控件 ListView

在学习了 ScrollView 及 Adapter 两节内容之后,大家应该对 ListView 有了一些基本的了解,它是一个列表样式的 ViewGroup,将若干 item 按行排列。ListView 是一个很基本的控件也是 Android 中最重要的控件之一。它可以帮助我们完成多个 View 的垂直排列并支持滚动显示效果,而它比 ScrollView 更灵活也更易扩展,Adapter 作为 UI 控件和数据源之间的桥梁,会帮我们实现 MVC 模式,所以在实际开发中大多数的列表场景我们会优先考虑使用 ListView 来实现(目前 Google 推出了新的更强大的列表控件——RecyclerView,不过基本原理和 ListView 类似)。

1. ListView 的特性

ListView 在 Android App 中无处不在,比如最常用的“联系人”就可以通过 ListView 轻松实现。通过 ListView 用户可以上下滑动来浏览列表信息,我们可以在 ListView 中放置各种控件,比如 ImageView、Button、ToggleButton 等来丰富我们的列表样式。

正因为 ListView 通常是用来展示大量的数据集的控件,所以我们不可能挨个的为每个 item 去设置相应的数据,这时候就要借助 Adapter 来帮助我们完成 UI 控件和数据的绑定工作了。

2. ListView 的基本用法

ListView 相比其他控件来讲确实比较特殊,也有很多使用技巧,但是它作为一个 ViewGroup,同样也有自己的布局属性、 API 及事件监听器。

2.1 ListView 的常用属性

  • divider:
    设置 item 之间的分隔线,可以设置成颜色,也可以设置成 drawable 资源。
  • dividerHeight:
    设置分隔线的高度;
  • footerDividersEnabled:
    是否在 footerView(表尾)前绘制一个分隔线,默认为 true;
  • headerDividersEnabled:
    是否在 headerView(表首)前绘制一个分隔线,默认为 true;
  • android:scrollbars:
    设置滚动条样式,有两种样式: horizontal 和 vertical,以及 none 表示隐藏滚动条。

2.2 ListView 的常用 API

  • addHeaderView(View v):
    添加 headView,headView 会固定显示在表的第一个元素之前。参数是一个 View 对象,比如可以用作“下拉刷新”的 View;
  • addFooterView(View v):
    添加 footerView,footerView 会固定显示在表的最后一个元素之后。参数是一个 View 对象,比如可以用作“上拉加载更多”的 View;
  • addHeaderView(View v, Object data, boolean isSelectable):
    添加 headView,第二个参数表示与 headView 绑定的数据对象,第三个参数表示当前这条 item 是否可选中,通常“下拉刷新”可以设置成无法选中;
  • addFooterView(View v, Object data, boolean isSelectable):
    添加 footerView,第二个参数表示与 footerView 绑定的数据对象,第三个参数表示当前这条 item 是否可选中,通常“上拉加载更多”可设置成无法选中。

2.3 点击事件监听器

ListView 的样式示意图如下:

ListView 中的每个 item 可以设置成任意样式,可以包含任意的 Android 控件,非常灵活。接下来,我们来一起看看如何使用。

3. ListView 的使用示例

使用 ListView 就一定逃不开 Adapter,在上一节我们介绍了 ArrayAdapter 和 SimpleAdapter 配合 ListView 的使用方法,其实 ArrayAdapter 和 SimpleAdapter 都是继承 BaseAdapter 做的封装,那么这一节我们就来看看 BaseAdapter 究竟是何方神圣。为了让大家更好的看到对比,这一节我们用 BaseAdapter 来实现上一节的水果的列表。

3.1 自定义 Adapter

BaseAdapter 是一个接口,我们自定义 Adapter 就需要实现一个 BaseAdapter 接口,首先创建一个 MyAdapter 类实现 BaseAdapter 接口,如下:

package com.emercy.myapplication;

import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

public class MyAdapter extends BaseAdapter {
    @Override
    public int getCount() {
        return 0;
    }

    @Override
    public Object getItem(int position) {
        return null;
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        return null;
    }
}

可以看到,继承自 BaseAdapter 的类有 4 个方法是必须实现的,我们具体看看这四个方法分别表示什么以及如何实现:

  • public int getCount():
    返回列表的长度,即 ListView 需要展示的 item 数量。通常我们会将数据保存在 List 或者数组当中,从而可以通过数据或者 list 获取列表的长度返回即可。比如如果我们通过 ArrayList 保存列表的数据,那么我们可以通过 List 的 size() 方法获取列表的长度,并在 getCount() 回调方法中返回,如下:
    @Override
    public int getCount() {
      int count = arrayList.size();     // 计算数据 ArrayList 的长度
      return count;                     // 返回列表的长度
    }
    
  • public Object getItem(int position):
    获取位于 position 的 item 对应的数据内容,当 ListView 需要填充第 position 个 item 的时候会回调此函数获取当前 item 上应该显示的数据内容,如果数据存在 ArrayList 当中,直接返回当前 position 的 ArrayList 内容即可,如下:
    @Override
    public Object getItem(int i):
      return arrayList.get(i);        // item 对应的数据内容
    }
    
  • public long getItemId(int position) :
    返回当前行的 itemid,itemid 是唯一标识当前 item 的索引,通常情况下我们可以直接返回 position,如下:
    @Override
    public long getItemId(int i) {
      return i;
    }
    
  • public View getView(int position, View convertView, ViewGroup parent):
    当列表中的一个 item 即将被展示的时候系统会回调此函数,我们需要在此回调接口中完成数据与 UI 控件的绑定。通过LayoutInflater类获取布局对象,然后通过findViewById拿到具体的控件,并将数据内容设置到控件当中,比如我们需要在列表中设置一个图片资源:
    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
      view = inflter.inflate(R.layout.activity_gridview, null);      // 获取布局对象
      ImageView icon = (ImageView) view.findViewById(R.id.icon);     // 通过ID拿到具体的View对象
      icon.setImageResource(flags[i]);                               // 设置ImageView的图片资源
      return view;
    }
    

3.2 编写布局文件

为了对比学习,本例实现一个和上一节中 SimpleAdapter 的水果列表相同的例子,布局文件可直接引用,具体代码可以参考 第 23 节第 2 小节的内容。

3.3 创建数据模型

在 Adapter 中创建我们需要保存的数据,和上一节的例子一样,我们用两个数组分别保存水果名称和水果图片资源:

String[] mDataName = {"苹果", "梨", "香蕉", "桃子", "西瓜", "荔枝", "橘子"};
int[] mDataImage = {R.drawable.apple, R.drawable.pear, R.drawable.banana, R.drawable.peach,
            R.drawable.watermelon, R.drawable.lychee, R.drawable.orange, R.drawable.orange};

在 MyAdapter 中新增数据更新接口,用于初始数据的设置及后续数据的更新:
MyAdapter.java

public void setData(String[] name, int[] resId)

这样一来我们就有了数据源,接着按照 第 24 节 3.1 小节中对 4 个回调接口的描述修改回调方法体。主要是在getCount中返回数组长度,getView中通过 layout 对象获取到 TextView 和 ImageView,然后设置水果名称和图片,最终 MyAdapter 类的代码如下:

package com.emercy.myapplication;

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


public class MyAdapter extends BaseAdapter {

    private Context mContext;
    private String[] mName;
    private int[] mResId;

    public MyAdapter(Context context) {
        mContext = context;
    }

    public void setData(String[] name, int[] resId) {
        mName = name;
        mResId = resId;
    }


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

    @Override
    public Object getItem(int position) {
        return null;
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        convertView = LayoutInflater.from(mContext).inflate(R.layout.list_view, null);
        TextView name = convertView.findViewById(R.id.textView);
        ImageView image = convertView.findViewById(R.id.imageView);
        name.setText(mName[position]);
        image.setImageResource(mResId[position]);
        return convertView;
    }
}

3.4 编写主 Activity

ListView 的核心适配逻辑都在 Adapter 中完成,主 Activity 比较简单,主要做以下几件事:

  • 获取 listView 对象
  • 创建自定义 adapter,即 MyAdapter,并设置数据
  • 将自定义 Adapter 设置给 ListView
  • 设置 ListView 列表项的点击事件
    代码如下:
package com.emercy.myapplication;

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

public class MainActivity extends Activity {

    ListView mListView;
    String[] mDataName = {"苹果", "梨", "香蕉", "桃子", "西瓜", "荔枝", "橘子"};
    int[] mDataImage = {R.drawable.apple, R.drawable.pear, R.drawable.banana, R.drawable.peach,
            R.drawable.watermelon, R.drawable.lychee, R.drawable.orange, R.drawable.orange};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mListView = findViewById(R.id.listView);

        MyAdapter adapter = new MyAdapter(this);
        adapter.setData(mDataName, mDataImage);
        mListView.setAdapter(adapter);

        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                Toast.makeText(getApplicationContext(), mDataName[i], Toast.LENGTH_LONG).show();
            }
        });
    }
}

运行效果和上一节一样:

4. 小结

本节主要介绍了 ListView 搭配 BaseAdapter 实现列表功能的方法,BaseAdapter 比 ArrayAdapter 和 SimpleAdapter 拥有更大的可控性,我们可以自己实现很多复杂的功能。目前更推荐使用的是 Google 近年推出的 RecyclerView,不过基本原理和 ListView 类似,本节主要介绍的是基础的用法,在掌握了基本用法及核心思想之后,可以继续学习一些优化手段及高级用法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/545485.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

bugku-web-需要管理员

页面源码 <html> <head> <meta http-equiv"Content-Type" content"text/html; charsetUTF-8"> <title>404 Not Found</title> </head> <body> <div idmain><i> <h2>Something error:</h2…

指针的深入理解(七)

指针的深入理解&#xff08;七&#xff09; 个人主页&#xff1a;大白的编程日记 个人专栏&#xff1a;C语言学习之路 感谢遇见&#xff0c;我们一起学习进步&#xff01; 文章目录 指针的深入理解&#xff08;七&#xff09;前言一.常量字符串指针1.1常量字符串的理解1.2常量…

[蓝桥杯 2019 国 B] 解谜游戏

[蓝桥杯 2019 国 B] 解谜游戏 题目背景 题目描述 小明正在玩一款解谜游戏。谜题由 24 24 24 根塑料棒组成&#xff0c;其中黄色塑料棒 4 4 4 根&#xff0c;红色 8 8 8 根&#xff0c;绿色 12 12 12 根 (后面用 Y 表示黄色、R 表示红色、G 表示绿色)。初始时这些塑料棒排…

LangChain初学者指南

自从ChatGPT发布以来&#xff0c;大语言模型(LLM)得到极大普及。虽然大多数人没有足够资金和计算资源从头开始训练LLM&#xff0c;但仍然可以基于预训练的LLM来构建一些很酷的东西&#xff0c;例如: 可以根据个人数据与外界互动的个人助理为特定目的定制的聊天机器人对文档或代…

蚂蚁云科技集团正式发布以正教育大模型,专注因材施教

4月12日,蚂蚁云科技集团成功举办“智以育人、慧正无界——以正教育大模型产品发布会”,该产品致力于智慧教育变革,让因材施教成为可能。 上海科学技术交流中心科技企业服务处处长陈霖博士、中国信通院华东分院院长廖运发、上海市科协常委马慧民博士等出席并致辞;南威软件集团执…

设计模式之大话西游

8年前深究设计模式&#xff0c;现如今再次回锅&#xff5e; 还是大话设计模式 这本书还是可以的 大话西游经典的台词&#xff1a;“曾经有一份真挚的爱情摆在我面前,我没有珍惜,等我失去的时候,我才后悔莫及,人世间最痛苦的事莫过于此。如果上天能够给我一个再来一次的机会,我会…

Java多线程的线程状态和线程池参数

一、线程状态 当线程被创建并启动以后&#xff0c;它既不是一启动就进入了执行状态&#xff0c;也不是一直处于执行状态。线程对象在不同的时期有不同的状态。Java中的线程状态被定义在了java.lang.Thread.State枚举类中&#xff0c;State枚举类的源码如下&#xff1a; publi…

轻量级的Spring Cloud Gateway实践,实现api和websocket转发

当国内大部分都是粘贴复制一些重型框架时&#xff0c;有没有人会想到&#xff0c;我们自己做一个小项目&#xff0c;几个小的Spring boot的项目时&#xff0c;我们是否还需要按部就班的用我们公司中用到的Nacos&#xff0c;这种冗余且调配复杂的组件呢&#xff1f; 不是本人说…

软考报考指南

目录 了解软考 选择报考级别与专业 关注报考时间 完成报名手续 准备考试 参加考试 查询成绩与领取证书 了解软考 官网链接&#xff1a;中国计算机技术职业资格网 软考&#xff0c;即计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试&#xff0c;是由国家人…

广州网站建设如何吸引用户眼球

随着互联网技术的发展&#xff0c;现在广州的大多数企业或品牌都会打造高质量的网站&#xff0c;以便更好地宣传&#xff0c;在网站建设过程中&#xff0c;前端网站设计至关重要&#xff0c;主要体现在排版和布局上&#xff0c;高大尚的网站建设并不是将所有模块内容堆放在首页…

中仕公考:教师招聘和事业单位联考的区别

教师招聘考试与事业单位联考作为两种不同的职业资格考试&#xff0c;其在报考条件和考试内容上存在明显的差异&#xff0c;具体内容为大家简要介绍一下&#xff1a; 一、报考条件 1. 教师招聘考试&#xff1a;此类考试的报名通常要求申请者持有相关教师资格证明。对于非师范生…

使用阿里云试用Elasticsearch学习:Search Labs Tutorials 搭建一个flask搜索应用

文档&#xff1a;https://www.elastic.co/search-labs/tutorials/search-tutorial https://github.com/elastic/elasticsearch-labs/tree/main/example-apps/search-tutorial Full-Text Search

酷开系统让用户在方方面面享受科技进步带来的美好体验

电视本身的特性&#xff0c;再有人工智能和全时AI的加持&#xff0c;让搭载了酷开系统的电视有能力成为一个“家庭智慧管控中心”。互联网的存在让大家能更懒地完成事情&#xff0c;满足宅家的愿望&#xff0c;有话说&#xff0c;科技因懒人而进步。打个简单的比方&#xff0c;…

人工智能研究生前置知识—扩展程序库Pandas

人工智能研究生前置知识—扩展程序库Pandas pandas简介 Pandas 的主要数据结构是 Series &#xff08;一维数据&#xff09;与 DataFrame&#xff08;二维数据&#xff09;。Pandas 广泛应用在学术、金融、统计学等各个数据分析领域。 pandas的官网&#xff1a;https://pandas.…

护眼台灯哪个牌子最好,护眼台灯品牌排行榜分享

​护眼台灯哪个牌子最好&#xff1f;尽管一些家长可能对护眼台灯还不甚了解&#xff0c;下面我将介绍这类台灯的几个显著优势&#xff1a;它们专为减少眼睛疲劳和保护视力而设计&#xff0c;提供稳定且柔和的光线&#xff1b;具备灵活的亮度调节功能&#xff0c;适应不同的阅读…

springCloudAlibaba集成seata实战(分布式事物详解)

一、分布式事务 1. 事务介绍 1.1 基础概念 事务&#xff1a;保证我们多个数据库操作的原子性&#xff0c;多个操作要么都成功要么都不成功 事务ACID原则 A&#xff08;Atomic&#xff09;原子性&#xff1a;构成事务的所有操作&#xff0c;要么都执行完成&#xff0c;要么全部…

linux之shell命令

shell基础命令 浏览Linux 文件系统 Linux 系统目录结构 /bin&#xff1a; bin 是 Binaries (二进制文件) 的缩写, 这个目录存放着最经常使用的命令。 /boot&#xff1a; 这里存放的是启动 Linux 时使用的一些核心文件&#xff0c;包括一些连接文件以及镜像文件。 /dev &…

论文略读:Benign Oscillation of Stochastic Gradient Descent with Large Learning Rate

iclr 2024 reviewer评分 368 论文从理论上研究了通过随机梯度下降&#xff08;SGD&#xff09;且采用大学习率训练的神经网络&#xff08;NN&#xff09;的泛化特性论文的发现是&#xff0c;由于SGD的大学习率引起的NN权重的振荡&#xff0c;实际上有利于NN的泛化&#xff0c;…

如何用CRMEB Pro版企业微信功能做私域运营

过去3年&#xff0c;线下实体零售发展坎坷&#xff0c;线上经济趁机扩展&#xff0c;出现了社交电商、私域电商等多种电商类型。其中&#xff0c;私域电商备受关注&#xff0c;众多企业纷纷开始尝试&#xff0c;在广大企业商家做私域运营的过程中&#xff0c;企业微信以其强大的…

病毒繁殖-第12届蓝桥杯选拔赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第52讲。 病毒繁殖&#xf…