SwiftUI中List的liststyle样式及使用详解添加、移动、删除、自定义滑动

SwiftUI中的List可是个好东西,它用于显示可滚动列表的视图容器,类似于UITableView。在List中可以显示静态或动态的数据,并支持垂直滚动。List是一个数据驱动的视图,当数据发生变化时,列表会自动更新。针对List,我们还可以进行添加、移动、删除以及滑动等功能。示例代码:

//
//  RouterView.swift
//  SwiftBook
//
//  Created by song on 2024/7/4.
//import SwiftUIstruct RouterView: View {@State var monthes = ["January","February","March","April","May","June","July","August","September","October","November","December"]var body: some View {List(monthes, id: \.self) { m inText(m)}}
}#Preview {RouterView()
}

显示静态数据

显示静态的数据还是比较简单的,比如要显示12个月份,代码中,直接在List组件里面放置Text组件即可,不过如果同类型数据过多,还是采用动态数组的方式去显示。

显示动态数据

很多的时候采用的都是动态数组显示的方式,比如通过网络请求回来的数据,再通过List显示出来等等:

上面的代码简化了很多,我们将months数据作为第一个参数,传给了List,而List的第二个参数id,则表示months数据中的元素采用自身作为唯一的标识符。如果数组中的两个或多个元素不是唯一的,这可能会导致问题。

如果不用字符串数据,而是该用了实例对象数组,则可以将实例对象的结构实现Identifiable协议,该协议需要实现一个id属性,如果将一个实现了Identifiable协议的实例对象数组传给List,则不需要指定id参数了。比如下面的代码示例:

样式设置

默认的List是有背景色,Light模式下是白色,Dark模式下是灰色,比如下面这个代码: 

背景色

只需要添加一行代码即可,将其修饰在List闭包内部的组件上,即修饰在Text组件上。如果直接修饰在List组件上,则没有任何效果。 

内间距

另外上面的代码中,Text的宽度没有完全和cell的宽度对齐,两边还有一些间距,有的时候是不需要这个间距的,设置下面代码即可,同样是要修饰在List闭包内的组件上:

分割线颜色与隐藏

设置分割线以及是否显示需要将下面两个修饰符作用在List闭包内的组件上。

// 隐藏分割线,默认是显示的。
.listRowSeparator(.hidden)
// 设置分割线颜色。
.listRowSeparatorTint(.red)

设置Cell之间的间距

默认cell之间是采用分割线进行区分的,如果设置间距,则分割线直接就隐藏了。该修饰符需要作用在List组件上,效果如下图,设置了10个间距:

List样式

设置List样式可以通过在括号内需要传入对应的style参数。listStyle修饰符需要作用在List组件上。

automatic:默认列表样式,根据设备和环境自动选择合适的列表样式。
plain:普通列表样式。
grouped:分组列表样式。
insetGrouped:缩进分组列表样式。
sidebar:侧边栏列表样式。
inset:缩进列表样式。
以上样式的效果图如下,有些样式不太明显,结合其他的修饰符效果可能更好。

分组显示(Section、 Header、 Footer)

List组件要想实现分组的功能,很简单,在List组件中使用Section组件即可。Section组件支持Header和Footer功能,同时Header和Footer也支持直接设置Title和自定义。

比如下面直接设置Section title的示例,直接给Title一个字符串,在content闭包内通过ForEach循环添加要显示的组件,当然也可以不用循环,而是静态数据。

下面是自定义Header和Footer的示例,Header中横向显示了Image和Text组件,Footer中添加了一个Text,效果如下:

这里额外说一下List和ForEach循环的结合使用的场景:

如果只是单纯的显示一些静态数据,或者一个数据数据,只用List组件即可。
如果要显示数组数据,可以单独使用List组件,将数组数据传给List,也可以在List组件中添加ForEach组件,通过ForEach循环遍历数组数据。

  var body: some View {List {ForEach(fruits, id: \.self) { fruit inText(fruit.capitalized)}}}

如果即有静态数据又有动态数据要显示,则需List和ForEach组合使用:

上面的代码稍微有些多,主要为了视觉效果更好一些。从效果图中可以看出是人为设置了两个Header,采用了Text组件,并设置了相关的属性修饰符。代码中不难看出List组件里面采用了ForEach,同时也单独设置了Text组件。
另外需要提一下,我们给ForEach设置了前景颜色,这个前景颜色会作用在ForEach中的每个Text上。还有给Group组件设置了List cell的样式,那么这个样式也会作用在List中的每个子组件上,这样做代码会更加简洁明了。

添加和删除元素
只能在List的动态部分添加和删除元素,而静态元素不能在应用程序运行时添加或删除。因此,我们的列表需要完全动态,或者至少包含一个动态部分,以便我们能够添加或删除元素。

为了有添加和删除的入口,我们添加了导航栏,并设置了导航栏的toolbar,导航栏的设置这里不过多阐述。

添加元素
在导航栏的右侧添加了一个添加元素的按钮,点击后在List要展示的数据中添加元素,此时也要求该数据必须被@State包裹修饰,以便其修改后触发UI刷新。具体代码见下面效果图。

删除元素
在导航栏左侧添加了一个EditButton,点击后将整个List设置为编辑模式,并在每个cell的左侧提供一个红色的删除按钮。这个过程主要是由系统自动的。不过前提是要对List添加至少一个可操作的方法,比如onDelete,onMove等,否则点击了EditButton,List也没有任何变化。
另外对单个cell进行左滑操作也可以删除元素。

为了实现删除效果,需要在ForEach上添加onDelete方法,如下:

.onDelete(perform: { indexSet in})

这个onDelete方法返回一个IndexSet类型的值,我们可以在这个闭包内进行数据删除,不过为了UI逻辑和业务逻辑低耦合,采用单独抽出来一个方法处理删除逻辑,如下:

func deleteItem(indexSet: IndexSet) {fruits.remove(atOffsets: indexSet)
}

在deleteItem方法里面,fruits数组调用remove(atOffsets:)方法即可。

因为onDelete方法返回一个IndexSet类型的值,所以抽出来的方法同样接受这样类型的值。最终只要在ForEach上调用下面代码即可,不用额外写传递的参数:

ForEach(fruits, id: \.self) { fruit inText(fruit.capitalized)
}
.onDelete(perform: deleteItem)

最终代码及效果如下图:

移动功能

移动功能还是比较普遍的,基于上面的代码,只需要在ForEach上添加下面的方法即可。

.onMove(perform: { indices, newOffset in})

这个方法返回两个参数,第一个为IndexSet类型的值,第二个为Int类型的值。同onDelete一样,我们单独抽出来一个方法,同样接收这两个参数。

func moveItem(indexSet: IndexSet, offSet: Int) {fruits.move(fromOffsets: indexSet, toOffset: offSet)
}

在moveItem方法中,fruits数据调用move(fromOffsets:, toOffset:)方法即可。最后在ForEach上添加该方法:

ForEach(fruits, id: \.self) { fruit inText(fruit.capitalized)
}
.onMove(perform: moveItem)

实现了上面的代码后,我们可以在List的编辑模式下拖动cell移动,编辑模式下每个cell右侧有三个横杠的图标,拖动即可移动。另外非编辑模式下长按cell后也可以进行拖动,代码及效果图如下:

 

自定义左滑功能

SwiftUI的swipeActions()修饰符允许你添加一个或多个滑动动作按钮到你的列表行,可选地控制他们属于哪一边,以及他们是否应该被触发使用一个完整的滑动。
先看下代码及效果图: 

swipeActions()方法有三个参数,第一个edge决定操作按钮放哪边;第二个allowsFullSwipe决定完全滑动是否自动执行第一个操作,默认值为true;第三个即是内容闭包了。

关于样式,只能通过tint设置背景色,如果不设置,系统默认是灰色的。
SwiftUI底层还是很聪明的,比如第一个Button,我们用Text显示内容,只有文字,那么系统就显示了Add文字,第二个和第三个用Label显示,有文字和图片,但是系统聪明的只显示了图片。

对于想要拥有删除功能的按钮,应该使用Button(role: .destructive),而不是仅仅指定一个红色背景色,比如上面第三个按钮,不需要有任何删除的逻辑,聪明的底层帮我们实现了。

Button(role: .destructive) {} label: {Label("Delete", systemImage: "trash.fill")
}

SwiftUI中的List确实是一个非常好用的组件,包含的功能也比较多,大多数的App界面也都是由导航栏和List组成的。

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

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

相关文章

神领物流项目第一天

文章目录 聚焦快递领域首先第一个是验证码模块流程登录接口权限管家 聚焦快递领域 首先第一个是验证码模块流程 首先生成验证码的流程 可以使用工具类去生成验证码 LineCaptcha lineCaptcha CaptchaUtil.createLineCaptcha(160, 60, 4, 26);// 获取值然后存入redis中 strin…

【HarmonyOS4学习笔记】《HarmonyOS4+NEXT星河版入门到企业级实战教程》课程学习笔记(二十二)

课程地址: 黑马程序员HarmonyOS4NEXT星河版入门到企业级实战教程,一套精通鸿蒙应用开发 (本篇笔记对应课程第 32 节) P32《31.通知-基础通知》 基础文本类型通知:briefText 没有用,写了也白写。 长文本类型…

【东奥会计-注册安全分析报告】

前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 暴力破解密码,造成用户信息泄露短信盗刷的安全问题,影响业务及导致用户投诉带来经济损失,尤其是后付费客户,风险巨大,造成亏损无底洞…

elasticsearch-users和elasticsearch-reset-password介绍

elasticsearch 内置 elastic, kibana, logstash_system,beats_system 共4个用户,用途如下: elastic 账号:内置的超级用户,拥有 superuser 角色。 kibana 账号:用来连接 elasticsearch 并与之通信。Kibana 服务器以该用…

【HICE】基于用户认证的虚拟服务搭建

1.创建特定的内容 --账号与密码(需要认证访问)【里面】 2.编辑配置1.conf的内容,更新httpd 3.编辑hehe网页(外部公开) cd /www/ echo hehe > hehe/index.html 4.更改本地hosts和window下的解析 5.浏览器下验证内…

OpenCV基础(1)

目录 安装OpenCV 读取图像 显示图像 cv2.waitKey()函数 cv2.destroyAllWindows()函数 保存图像 读取视频 开启摄像头 图像处理 像素处理 二值图像及灰度图像 彩色图像及通道处理 调整图像大小 感兴趣区域 掩模 掩模基础及构造 掩模作为函数参数 色彩处理 色…

CSRF漏洞攻击

05-CSRF 1 CSRF概述 1.1 概述 CSRF (Cross-Site Request Forgery) 跨站请求伪造,也可称为一键式攻击 (one-click-attack),通常缩写为 CSRF 或者 XSRF。 CSRF 攻击是一种挟持用户在当前已登录的浏览器上发送恶意请求的攻击方法。相对于XSS利用用户对指…

wsl安装Linux系统到指定位置

默认情况下,wsl安装的系统,会安装到系统C盘,长期下去,很容易把C盘的空间消耗完,从而影响系统的正常运行,所以我建议是将wsl所有的系统都安装到其它磁盘中,便于维护。 1、导出镜像 通过wsl -l -v 查看当前已安装的系统版本。 导出到当前目录位置,也可以指定目录位置。 w…

docker集群部署主从mysql

搭建一个mysql集群,1主2从,使用docker容器 一、创建docker的mysql镜像 下次补上,因为现在很多网络不能直接pull,操作下次补上。 二、创建mysql容器 创建容器1 docker run -it -d --name mysql_1 -p 7001:3306 --net mynet --…

《昇思25天学习打卡营第10天|使用静态图加速》

文章目录 今日所学:一、背景介绍1. 动态图模式2. 静态图模式 三、静态图模式的使用场景四、静态图模式开启方式1. 基于装饰器的开启方式2. 基于context的开启方式 总结: 今日所学: 在上一集中,我学习了保存与加载的方法&#xff…

昇思25天学习打卡营第6天|简单的深度学习模型实战 - 函数式自动微分

自动微分(Automatic Differentiation)是什么?微分是函数在某一处的导数值,自动微分就是使用计算机程序自动求解函数在某一处的导数值。自动微分可用于计算神经网络反向传播的梯度大小,是机器学习训练中不可或缺的一步。 这些公式难免让人头大…

论文浅尝 | 从最少到最多的提示可在大型语言模型中实现复杂的推理

笔记整理:王泽元,浙江大学博士 链接:https://openreview.net/forum?idWZH7099tgfM 1. 动机 尽管深度学习已经取得了巨大的成功,但它与人类智慧仍然存在一些明显差距。这些差距包括以下几个方面:1)学习新任…

【代码大全2 选读】看看骨灰级高手消灭 if-else 逻辑的瑞士军刀长啥样

文章目录 1 【写在前面】2 【心法】这把瑞士军刀长啥样3 【示例1】确定某个月份的天数(Days-in-Month Example)4 【示例2】确定保险费率(Insurance Rates Example)5 【示例3】灵活的消息格式(Flexible-Message-Format …

14-27 剑和诗人 1 – 请称呼我AI工程师

​​​​​ 仅初创企业的收入就超过 10 亿美元,随着 Gen AI 的早期成功迹象,每家有远见的科技公司都在竞相将 Gen AI 功能融入其产品、客户支持机器人和营销中。作为一种技术,AI 正处于与 90 年代末互联网相似的阶段,甚至完全相同…

【unity实战】Unity中使用A*寻路+有限状态机制作一个俯视角敌人AI

最终效果 文章目录 最终效果前言A*寻路插件介绍下载导入AI插件生成寻路网格节点的类型障碍物寻路测试A*只打印报错信息 代码控制寻路动画配置敌人状态机各种状态脚本效果完结 前言 前面做过有限状态机制作一个敌人AI:【unity实战】在Unity中使用有限状态机制作一个…

vxe-table合并行数据;element-plus的el-table动态合并行

文章目录 一、vxe-table合并行数据1.代码 二、使用element-plus的el-table动态合并行2.代码 注意&#xff1a;const fields 是要合并的字段 一、vxe-table合并行数据 1.代码 <vxe-tableborderresizableheight"500":scroll-y"{enabled: false}":span-m…

信创-办公软件应用工程师认证

随着国家对信息技术自主创新的战略重视程度不断提升&#xff0c;信创产业迎来前所未有的发展机遇。未来几年内&#xff0c;信创产业将呈现市场规模扩大、技术创新加速、产业链完善和国产化替代加速的趋势。信创人才培养对于推动产业发展具有重要意义。应加强高校教育、建立人才…

【信息学奥赛】CSP-J/S初赛07 排序算法及其他算法在初赛中的考察

本专栏&#x1f449;CSP-J/S初赛内容主要讲解信息学奥赛的初赛内容&#xff0c;包含计算机基础、初赛常考的C程序和算法以及数据结构&#xff0c;并收集了近年真题以作参考。 如果你想参加信息学奥赛&#xff0c;但之前没有太多C基础&#xff0c;请点击&#x1f449;专栏&#…

C++|海康摄像头实时预览时设置音量大小

使用海康API设置音量的函数是&#xff1a;NET_DVR_OpenSound。 在实际代码中我遇到了以下问题&#xff1a; 1&#xff1a;调用NET_DVR_OpenSound接口一直返回失败&#xff0c;错误是调用顺序出错。 2&#xff1a;音量设置不成功。 对于以上两种问题&#xff0c;我相信很多人…

FineBI在线学习资源-数据处理

FineBI在线学习资源汇总&#xff1a; 学习资源 视频课程 帮助文档 问答 数据处理学习文档&#xff1a; 相关资料&#xff1a; 故事背景概述-https://help.fanruan.com/finebi6.0/doc-view-1789.html 基础表处理-https://help.fanruan.com/finebi6.0/doc-view-1791.html …