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 {@Overridepublic int getCount() {return 0;}@Overridepublic Object getItem(int position) {return null;}@Overridepublic long getItemId(int position) {return 0;}@Overridepublic 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;}@Overridepublic int getCount() {return mName.length;}@Overridepublic Object getItem(int position) {return null;}@Overridepublic long getItemId(int position) {return position;}@Overridepublic 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};@Overrideprotected 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() {@Overridepublic 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 类似,本节主要介绍的是基础的用法,在掌握了基本用法及核心思想之后,可以继续学习一些优化手段及高级用法。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Udio——革命性的AI音乐生成软件

Udio是一款革命性的AI音乐生成软件&#xff0c;由前谷歌DeepMind的顶尖AI研究人员和工程师共同创立&#xff0c;得到著名风险投资公司a16z的支持。它旨在为音乐爱好者和专业人士提供一个全新的音乐创作和分享平台。用户可以通过文本提示来生成音乐&#xff0c;支持广泛的音乐风…

水牛社:打造你的居家副业利器,让赚钱变得更简单

水牛社&#xff0c;这个已经陪伴我们走过九个春秋的综合性网络任务和项目资源整合平台&#xff0c;真的给我留下了深刻的印象。它不仅仅是一个资源的汇聚地&#xff0c;更是一个帮助无数人实现网络副业梦想的平台。作为一个资深用户&#xff0c;我深感其中的价值和魅力。 水牛…

“香港批准比特币、以太坊ETF”!华夏、博时、嘉实计划发行相关产品!美国ETF分析师泼冷水:别指望香港ETF会有很大流量!

周一(4月15日)&#xff0c;比特币短线迎来反弹行情&#xff0c;币价回升至66000美元上方。华夏基金、博时国际与嘉实投资3家中国头部基金宣布&#xff0c;旗下虚拟资产现货ETF获准在香港发行。 据了解&#xff0c;华夏基金&#xff08;香港&#xff09;现计划发行能够投资于现货…

两部电话机怎样能实现对讲?直接连接能互相通话吗?门卫门房传达室岗亭电话怎么搞?

目录 两部电话机能直接连接吗&#xff1f;用三通头分出来一条电话线两部电话机用一根电话线直接连接能互相通话吗&#xff1f; 什么电话机可以直接连接两部IP电话机&#xff08;网络电话机&#xff09;可以直接连接两部普通电话机之间通过一个电话交换机也可以连接跨区域的两部…

mfc 带有复选框的ListBox

mfc 带有复选框的 ListBox 效果&#xff1a; 添加 ListBox 控件 从工具箱拖拽 ListBox 控件到窗口上&#xff0c;并设置属性&#xff1a; 包含字符串&#xff1a;true所有者描述&#xff1a;Fixed 给ListBox添加控制变量 添加完后&#xff0c;将m_list_box的类型使用CC…

react使用npm i @reduxjs/toolkit react-redux

npm i reduxjs/toolkit react-redux 创建一个 store文件夹&#xff0c;里面创建index.js文件和子模块文件夹 index,js文件写入以下代码 import {configureStore} from reduxjs/toolkit // 导入子模块 import counterReducer from ./modules/one import two from ./modules/tw…

OpenBayes 在线教程|张国荣、鲁迅等老照片秒变高清!即刻上手的超火 SUPIR-AI 图像修复教程

小伙伴们&#xff0c;大家在生活中是不是也会遇到这样的烦恼&#xff1a;心心念念想要打印一张充满回忆的老照片或酷炫动漫壁纸&#xff0c;却发现图像糊得像打了马赛克&#xff1f; 市面上的图像修复工具五花八门&#xff0c;选择困难症人群找得快要崩溃&#xff1f; 终于找…

Linux: softirq 简介

文章目录 1. 前言2. softirq 实现2.1 softirq 初始化2.1.1 注册各类 softirq 处理接口2.1.2 创建 softirq 处理线程 2.2 softirq 的 触发 和 处理2.1.1 softirq 触发2.1.2 softirq 处理2.1.2.1 在 中断上下文 处理 softirq2.1.2.2 在 ksoftirqd 内核线程上下文 处理 softirq 3.…

电子烟特效音语音方案选型-WTN6020-8S-E

随着科技的迅猛进步&#xff0c;电子烟行业亦在持续创新与突破&#xff0c;引领着全新的潮流。其中&#xff0c;电子烟产品所特有的吸烟声音特效播报功能&#xff0c;无疑成为了技术革新的璀璨亮点。这一设计巧妙地将吸烟的声效融入使用体验中&#xff0c;使得用户在吸电子烟时…

CSS3 立体 3D 变换

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;HTML5和CSS3悦读 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; 文章目录 ✍CSS3 立体 3D 变换&#x1f48e;1 坐标轴&#x1f48e;2 perspective 透视视…

linux管理进程

一、程序 程序&#xff1a;执行特定任务的一串代码 1.是一组计算机能识别和执行的指令&#xff0c;运行于电子计算机上&#xff0c;满足人们某种需求的信息化工具 2.用于描述进程要完成的功能&#xff0c;是控制进程执行的指令集 二、进程和线程 1.进程 进程是程序的执行…

vue2 二次封装element 组件,继承组件原属性,事件,插槽 示例

测试页面代码 这里主要记录如何封装element的el-input 并且封装后具有el-input原本的属性 事件 插槽 下面为测试页面即组件调用 <script> import CustomInput from /components/CustomInput.vue;export default {name: TestPage,components: { CustomInput },data() …

jenkins构建微信小程序并展示二维码

测试小程序的过程中&#xff0c;很多都是在回头和前端开发说一句&#xff0c;兄弟帮我打一个测试版本的测试码&#xff0c;开发有时间的情况下还好&#xff0c;就直接协助了&#xff0c;但是很多时候他们只修复了其中几个bug&#xff0c;其他需要修复的bug代码正在编写&#xf…

【蓝桥杯嵌入式】蓝桥杯嵌入式第十四届省赛程序真题,真题分析与代码讲解

&#x1f38a;【蓝桥杯嵌入式】专题正在持续更新中&#xff0c;原理图解析✨&#xff0c;各模块分析✨以及历年真题讲解✨都已更新完毕&#xff0c;欢迎大家前往订阅本专题&#x1f38f; &#x1f38f;【蓝桥杯嵌入式】蓝桥杯第十届省赛真题 &#x1f38f;【蓝桥杯嵌入式】蓝桥…

BTI功能验证与异常解析

BTI分支目标识别精讲与实践系列 思考 1、什么是代码重用攻击&#xff1f;什么是ROP攻击&#xff1f;区别与联系&#xff1f; 2、什么是JOP攻击&#xff1f;间接分支跳转指令&#xff1f; 3、JOP攻击的缓解技术&#xff1f;控制流完整性保护&#xff1f; 4、BTI下的JOP如何…

论文略读:Window Attention is Bugged: How not to Interpolate Position Embeddings

iclr 2024 reviewer 打分 6666 窗口注意力、位置嵌入以及高分辨率微调是现代Transformer X CV 时代的核心概念。论文发现&#xff0c;将这些几乎无处不在的组件简单地结合在一起&#xff0c;可能会对性能产生不利影响问题很简单&#xff1a;在使用窗口注意力时对位置嵌入进行插…

密码学 | 椭圆曲线数字签名方法 ECDSA(下)

目录 10 ECDSA 算法 11 创建签名 12 验证签名 13 ECDSA 的安全性 14 随机 k 值的重要性 15 结语 ⚠️ 原文&#xff1a;Understanding How ECDSA Protects Your Data. ⚠️ 写在前面&#xff1a;本文属于搬运博客&#xff0c;自己留着学习。同时&#xff0c;经过几…

C++设计模式|创建型 2.工厂模式

1.简单工厂思想 简单工厂模式不属于23种设计模式之⼀&#xff0c;更多的是⼀种编程习惯。它的核心思想是将产品的创建过程封装在⼀个⼯⼚类中&#xff0c;把创建对象的流程集中在这个⼯⼚类⾥⾯。卡码网将其结构描述为下图所示的情况&#xff1a; 简单⼯⼚模式包括三个主要⻆⾊…

鸿蒙端云一体化开发--调用云函数--适合小白体制

如何实现在端侧调用云函数&#xff1f; 观看前&#xff0c;友情提示&#xff1a; 不知道《如何一键创建端云一体化模板》的小白同学&#xff0c;请看&#xff1a; 鸿蒙端云一体化开发--开发云函数--适合小白体制-CSDN博客 实现方法&#xff1a; 第一步&#xff1a;添加依赖 …

3D视觉引导麻袋拆垛破包 | 某大型化工厂

客户需求 此项目为大型化工厂&#xff0c;客户现场每日有大量麻袋拆垛破包需求&#xff0c;麻袋软包由于自身易变形、码放垛型不规则、运输后松散等情况&#xff0c;无法依靠机器人示教位置完成拆垛。客户遂引入3D视觉进行自动化改造。 工作流程&#xff1a; 3D视觉对紧密贴合…