SwiftUI 6.0(iOS/iPadOS 18)中全新的 Tab 以及 Sidebar+悬浮 TabView 样式

在这里插入图片描述

概览

看来苹果一直对 iPadOS 中标签栏(TabView)不甚满意。这不,在 WWDC 2024 中苹果又对 TabView 外观做了大幅度的进化。

在这里插入图片描述

现在我们可以在顶部悬浮条和左侧的 Sidebar 两种不同布局之间恣意切换 TabView 的外观啦。而且,这在 SwiftUI 6.0 中显得尤为简单。

在本篇博文中,您将学到如下内容:

  • 概览
  • 1. iPadOS 18 中全新的 Sidebar+悬浮 TabView 样式
  • 2. 新 TabView 样式在 iOS 18 中的表现
  • 3. SwiftUI 6.0 新的 Tab 和 TabSection 原生视图
  • 4. 让 Tab 懂你所选
  • 5. 调整 Tab 的显示位置
  • 总结

看来 iPadOS 18 对 TabView 外观和功能都做了重量级的升级,那小伙伴们还等什么呢?

Let‘s find out!!!😉


1. iPadOS 18 中全新的 Sidebar+悬浮 TabView 样式

为了最大化利用屏幕空间,从 iPadOS 18 开始苹果有史以来第一次将位于底部的 TabView:

在这里插入图片描述

神奇的变为悬浮条置于窗口的顶部:

在这里插入图片描述

从上面两张图中我们可以对比在 iPadOS 18 中系统默认的时钟 App 中标签栏的新外观。

当需要显示悬浮条内额外标签页的内容时,我们还可以轻按最左侧的展开按钮将其变形为 Sidebar 模式以便将所有标签项一览无遗:
在这里插入图片描述

不仅如此,我们还可以恣意调整 Sidebar 和悬浮条中标签项的位置、将它们打包到组中显示,甚至定制它们的外观:

在这里插入图片描述

在这里插入图片描述

按苹果的话来说:标签栏的新外观可以最大化利用显示空间,并让我们的 App 极具现代化外观的范儿。 我们可以在悬浮条和 Sidebar 两者间随意切换从而解决了“麻雀虽小”和“面面俱到”之间鱼与熊掌不可兼得的问题。

2. 新 TabView 样式在 iOS 18 中的表现

为了能保持 iPadOS 18 中新 TabView 的延展性,在 iOS 18 中新的标签栏会“退化”为之前经典的样式。

在这里插入图片描述

与之前经典 TabView 外观类似:新的 TabView 在 iOS 18 中右侧额外显示不下的内容也会统统放到单独的 More 标签项中去。

所不同的是,iOS 18 新标签栏中的标签组(TabSection)会消失的“无影无踪”,其中的标签会被直接放在底部的标签栏中。

有些小伙伴们可能会好奇:iPhone pro max 大屏设备横屏时新的 TabView 会有怎样的表现?
在这里插入图片描述

上面就是 iPhone pro max 横屏时新标签栏在 iOS 18 中的样子。可以看到:除了最右侧 More 标签中的内容被平铺显示以外和之前并无二致。所以想利用大屏 iPhone 设备适配新 TabView 悬浮条外观的小伙伴们可能要暂时失望了。

了解完 iOS 18 中新标签栏的模样之后,下面就让我们来看看如何用代码展现它们吧。

在 SwiftUI 6.0 中适配 TabView 新外观超级简单,然我们马上来撸码为证!

3. SwiftUI 6.0 新的 Tab 和 TabSection 原生视图

从 SwiftUI 6.0 开始,苹果增加了全新的 Tab 和 TabSection 原生视图,专门为新 TabView 来效“犬马之劳”:

在这里插入图片描述
在这里插入图片描述
其中,Tab 被用来取代原来的 tabItem() 修改器,而 TabSection 则用来将多个 Tab 汇聚成组。

在 iPadOS 18 之前,我们是这样描述 TabView 外观的:

struct ContentView: View {@Environment(\.horizontalSizeClass) var hSize@State var tabSelecting = TabValue.allTopics@State var moveFromLeading = truevar body: some View {TabView(selection: $tabSelecting) {AnimSubView(title: "Main", bgColor: .white, imageName: "main", isMoveFromLeading: moveFromLeading).tabItem {Label("Main", systemImage: "house")}.tag(TabValue.main)AnimSubView(title: "This is the blog page", bgColor: .yellow, isMoveFromLeading: moveFromLeading).tabItem {Label("Topics", systemImage: "pencil")}.tag(TabValue.allTopics)AnimSubView(title: "SwiftUI topic", bgColor: .purple.opacity(0.3), isMoveFromLeading: moveFromLeading).tabItem {Label("SwiftUI", systemImage: "swift")}.tag(TabValue.swiftUI)AnimSubView(title: "Concurrency topic", bgColor: .green, isMoveFromLeading: moveFromLeading).tabItem {Label("Concurrency", systemImage: "timelapse")}.tag(TabValue.concurrency)AnimSubView(title: "Persistence topic", bgColor: .blue.opacity(0.3), isMoveFromLeading: moveFromLeading).tabItem {Label("Persistence", systemImage: "swiftdata")}.tag(TabValue.persistence)AnimSubView(title: "Search the site", bgColor: .cyan, isMoveFromLeading: moveFromLeading).tabItem {Label("Search", systemImage: "magnifyingglass")}.tag(TabValue.search)}.safeAreaInset(edge: .bottom) {Text("当前选中:\(tabSelecting)").font(.title2.weight(.heavy)).foregroundStyle(.white.gradient).padding().background(RoundedRectangle(cornerRadius: 15).foregroundStyle(.mint.gradient)).shadow(radius: 3.0)}.safeAreaPadding(.bottom, hSize == .compact ? 100 : 0).onChange(of: tabSelecting) {old,new in// 为标签切换增加转场动画支持...}.tint(.pink)}
}

可以看到:在 TabView 中我们使用 tabItem() 和 tag() 修改器用来构建每一个标签页。

而在新的 iPadOS 18 和 iOS 18 中,我们彻底抛弃了这两个修改器而改为使用 Tab 和 TabSection 视图来描述每个标签页:

struct ContentView: View {@State var moveFromLeading = truevar body: some View {TabView {Tab("Main", systemImage: "house") {AnimSubView(title: "Main", bgColor: .white, imageName: "main", isMoveFromLeading: moveFromLeading)}TabSection("Blog") {Tab("All topics", systemImage: "pencil") {AnimSubView(title: "This is the blog page", bgColor: .yellow, isMoveFromLeading: moveFromLeading)}Tab("SwiftUI", systemImage: "swift") {AnimSubView(title: "SwiftUI topic", bgColor: .purple.opacity(0.3), isMoveFromLeading: moveFromLeading)}Tab("Concurrency", systemImage: "timelapse") {AnimSubView(title: "Concurrency topic", bgColor: .green, isMoveFromLeading: moveFromLeading)}Tab("Persistence", systemImage: "swiftdata") {AnimSubView(title: "Persistence topic", bgColor: .blue.opacity(0.3), isMoveFromLeading: moveFromLeading)}}// 更多的 TabSectionsTab(role: .search) {AnimSubView(title: "Search the site", bgColor: .cyan, isMoveFromLeading: moveFromLeading)}}.tint(.pink)}
}

小伙伴们可以留意一下,在上面的代码中我们是如何使用 TabSection 将若干 Tab 聚合成组的。

运行可以看到,原本底部的标签栏化身为悬浮条一跃横空出世了:

在这里插入图片描述

要想让标签栏进一步支持 Sidebar 切换显示,我们只需将 .sidebarAdaptable 样式应用在 TabView 上即可:

TabView {...
}
.tabViewStyle(.sidebarAdaptable)

在这里插入图片描述


值得注意的是:要想 iOS 18 之前的标签栏旧语法支持悬浮条显示,我们无需修改半行代码。

而只需一行 tabViewStyle(.sidebarAdaptable) 语句的加持,我们也同样可以让旧标签栏支持 Sidebar 样式。


4. 让 Tab 懂你所选

现在我们新的 TabView 已经灵动的“跃然于纸上”了,不过如果我们希望动态跟踪用户选择了哪个 Tab 又该如何是好呢?

在 iOS 18 中使用 tag() 标识标签页的方式已经被废弃,取而代之的是全新的包含 value 参数的 Tag 构造器方法:

在这里插入图片描述

注意该 Tab 构造器必须放在 TabView(selection:) 特定的构造器闭包中才能编译通过。

struct ContentView: View {@Environment(\.horizontalSizeClass) var hSize@State var tabSelecting = TabValue.allTopics@State var moveFromLeading = truevar body: some View {TabView(selection: $tabSelecting) {Tab("Main", systemImage: "house", value: .main) {AnimSubView(title: "Main", bgColor: .white, imageName: "main", isMoveFromLeading: moveFromLeading)}TabSection("Blog") {Tab("All topics", systemImage: "pencil", value: TabValue.allTopics) {AnimSubView(title: "This is the blog page", bgColor: .yellow, isMoveFromLeading: moveFromLeading)}Tab("SwiftUI", systemImage: "swift", value: .swiftUI) {AnimSubView(title: "SwiftUI topic", bgColor: .purple.opacity(0.3), isMoveFromLeading: moveFromLeading)}                Tab("Concurrency", systemImage: "timelapse", value: .concurrency) {AnimSubView(title: "Concurrency topic", bgColor: .green, isMoveFromLeading: moveFromLeading)}Tab("Persistence", systemImage: "swiftdata", value: .persistence) {AnimSubView(title: "Persistence topic", bgColor: .blue.opacity(0.3), isMoveFromLeading: moveFromLeading)}}Tab(value: .search, role: .search) {AnimSubView(title: "Search the site", bgColor: .cyan, isMoveFromLeading: moveFromLeading)}}.tabViewStyle(.sidebarAdaptable).safeAreaInset(edge: .bottom) {Text("当前选中:\(tabSelecting)").font(.title2.weight(.heavy)).foregroundStyle(.white.gradient).padding().background(RoundedRectangle(cornerRadius: 15).foregroundStyle(.mint.gradient)).shadow(radius: 3.0)}.safeAreaPadding(.bottom, hSize == .compact ? 100 : 0).onChange(of: tabSelecting) {old,new in// 标签切换转场动画支持代码从略...}.tint(.pink)}
}

现在,我们已经能够捕获到用户当前选择的标签页啦:

在这里插入图片描述

5. 调整 Tab 的显示位置

除了在 TabView 中用 Tab 和 TabSection 妥善放置各个标签页以外,我们还可以进一步决定它们到底能够在何处显示。

这是通过 tabPlacement() 修改器方法来实现的:

在这里插入图片描述

其中对于 TabPlacement 类型的参数值我们有 3 种选择:

在这里插入图片描述

比如假若我们希望将 TabSection(“Blog”) 内部中间两个 Tab 始终放在悬浮条里,我们可以分别为其调用 .tabPlacement(.pinned) 修改器方法:

TabSection("Blog") {Tab("All topics", systemImage: "pencil", value: TabValue.allTopics) {AnimSubView(title: "This is the blog page", bgColor: .yellow, isMoveFromLeading: moveFromLeading)}Tab("SwiftUI", systemImage: "swift", value: .swiftUI) {AnimSubView(title: "SwiftUI topic", bgColor: .purple.opacity(0.3), isMoveFromLeading: moveFromLeading)}.tabPlacement(.pinned)Tab("Concurrency", systemImage: "timelapse", value: .concurrency) {AnimSubView(title: "Concurrency topic", bgColor: .green, isMoveFromLeading: moveFromLeading)}.tabPlacement(.pinned)Tab("Persistence", systemImage: "swiftdata", value: .persistence) {AnimSubView(title: "Persistence topic", bgColor: .blue.opacity(0.3), isMoveFromLeading: moveFromLeading)}
}

现在,这两个标签项会一如既往的驻留在顶部的悬浮条中,棒棒哒:

在这里插入图片描述

总结

在本篇博文中,我们介绍了 SwiftUI 6.0(iPadOS 18/iOS 18)新标签页中新增的 Tab 和 TabSection 原生视图,并进一步讨论了如何让 TabView 支持 Sidebar 样式以及其它有趣的新特性。

感谢观赏,再会!😎

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

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

相关文章

(超详细)基于动态顺序表实现简单的通讯录项目

前言: 我们在上一章节用c语言实现了线性表中的的动态顺序表,那么顺序表就只是顺序表吗?当然不是,使用顺序表结构可以实现很多项目,许多项目的数据结构都会用到顺序表,本章节我们就要使用顺序表实现一个简易…

腾讯云部署的java服务,访问阿里云的mysql数据库,带宽异常偏高,可能是什么原因

个人名片 🎓作者简介:java领域优质创作者 🌐个人主页:码农阿豪 📞工作室:新空间代码工作室(提供各种软件服务) 💌个人邮箱:[2435024119qq.com] &#x1f4f1…

js语音识别,语音转文字,speech recognition(需要翻墙才能识别)

先上代码 <!DOCTYPE html> <html><head><meta charset"utf-8"><meta name"viewport" content"widthdevice-width,initial-scale1.0"><title>test</title> </head><body><div id"…

人工智能的头号威胁:投毒攻击

随着掌管数字生活入口的万亿美元俱乐部企业——苹果公司跳入人工智能&#xff08;AI&#xff09;赛道&#xff0c;AI技术民主化的大幕正式拉开&#xff0c;同时也将AI安全问题推向舆论的风口浪尖。 根据瑞银本周一的智能手机调查报告&#xff0c;在中国以外的智能手机用户中&am…

Java多线程基础知识-2

线程的3个方法&#xff1a; Thread.sleep()&#xff1a;当前线程睡眠多少毫秒&#xff0c;让给其他线程去执行。 Thread.yield()&#xff1a;当前线程退出一下&#xff0c;进入到等待队列&#xff0c;让其他线程执行&#xff0c;即让出线程一下。 Thread.join()&#xff1a;…

《模拟联合国2.9—团队协作》

感谢上海财经大学持续的邀请&#xff0c;今天在阶梯教室举办的《模拟联合国2.0—团队协作》沙盘课程圆满结束。尽管场地的限制带来了一定的挑战&#xff0c;但得益于系统思考中“结构影响行为”的原则&#xff0c;我得以在不同场景中巧妙设计课程结构&#xff0c;极大地促进了大…

【JavaScript复习二】选择结构if和Switch(1)

### []( )2、单分支条件分支语句if (条件表达式) { // 条件为真时&#xff0c;做的事情 } else { // 条件为假时&#xff0c;做的事情 } ### []( )2,、多分支的 if 语句if (条件表达式1) { // 条件1为真时&#xff0c;做的事情} else if (条件表达式2) { // 条件1不满足&…

股票交易系统

效果展示&#xff0c;如下动图&#xff1a; 首先简述一下股票交易规则&#xff1a; 买卖股票&#xff0c;股民可以自行选择股票的买入或卖出价格和股票的数量&#xff0c;但是用户不一定马上就交易成功&#xff0c;只有当股票价格低于买入价才有机会买入&#xff0c;高于卖出价…

ccie在香港值钱吗?ccie认证很难考吗?

思科ccie认证可以算得上是网络高级工程师的一个标配证书&#xff0c;特别是在香港工作的朋友更是需要尽早拿下这个认证&#xff0c;它能让你的求职之路更为顺利。而已经入职的工程师为了不被时代所淘汰&#xff0c;也需要该证书保驾护航。 你知道ccie在香港值钱吗?ccie认证是不…

redis高可用-哨兵机制

一&#xff1a;背景 上一节我们已经实现了redis的主从同步&#xff0c;从而实现服务的流量分摊和数据高可用&#xff0c;但是出现故障以后&#xff0c;需要人工手动接入&#xff0c;手动切换主从&#xff0c;来实现故障转移。这是比较麻烦的&#xff0c;毕竟人不能实时盯着服务…

Covalent实现对1000亿笔链上交易解析,支持AI长期数据可用性

在区块链与人工智能&#xff08;AI&#xff09;交汇处&#xff0c;讨论往往集中于去中心化推理和去中心化训练等方面。然而&#xff0c;这一数据的关键组成部分却一直未得到足够的重视。一个主要问题是&#xff1a;我们如何保护 AI 模型中的数据不受偏见和操纵的影响&#xff1…

【计算机组成原理】指令系统考研真题详解之拓展操作码!

苏泽 “弃工从研”的路上很孤独&#xff0c;于是我记下了些许笔记相伴&#xff0c;希望能够帮助到大家 另外&#xff0c;利用了工作之余的一点点时间&#xff0c;整理了一套考研408的知识图谱&#xff0c; 我根据这一套知识图谱打造了这样一个408知识图谱问答系统 里面的每一…

C语言的网络编程

目录 引言 一、TCP/IP概述 1. TCP&#xff08;Transmission Control Protocol&#xff09; 2. UDP&#xff08;User Datagram Protocol&#xff09; 二、Socket编程基础 1. 服务器端 2. 客户端 三、URL与HTTP编程 1. 使用libcurl进行HTTP请求 表格总结 TCP/IP与Socke…

镭速传输界面优化之静态文件加载

镭速一直是众多企业传输大文件和大数据的优选对象&#xff0c;速度快、稳定且安全是市场上传输软件脱颖而出的立杆标签&#xff0c;那么同样在界面优化和体验的强大也能够给企业用户带来许多直观的感受&#xff0c;那么今天我们就来谈谈镭速是如何做到这些的&#xff0c;在界面…

【锐捷】VSU环境下部署VAC

配置要求 1.两台核心交换机部署VSU&#xff0c;Domain ID为1&#xff0c;S1的Switch ID为1&#xff0c;优先级为150&#xff0c;设备描述为VSU-S1&#xff1b;S2的Switch ID为2&#xff0c;优先级为120&#xff0c;设备描述为VSU-S2&#xff1b;两台设备的G0/48口用于BFD双机检…

go语言对接S3存储的SDK(支持minio和OSS)

背景 在某个项目中&#xff0c;客户要求支持S3协议的存储&#xff0c;因为之前的项目是go来开发的支持的oss和minio 。 但并不一定支持S3的协议&#xff0c;而且使用了二种SDK&#xff0c;感觉比较麻烦。 既然客户提出来了要求。那我们改一下就是了。 操作 引入 go语言中有对…

中国最全的hive sql 函数集合(持续更新)

#6/20/24 增加greatest函数&#xff1a; select greatest(1,2,3,4,5,2) 结论&#xff1a;可以用hive presto spark得出正确的结果值 #6/20/24 增加last_value(cl1) ignore nulls over(order by ts ) as dt 函数&#xff1a; 有数据集&#xff1a; 1 1 1 2 2   3 3 …

振幅调制与解调电路

本章学习内容与重难点 调制的原因 调制就是把低频信号的信息带到高频信号上。 减小天线长度 天线长度与所接收的信号的波长正相关&#xff0c;调制到高频再发送能极大幅度降低接收成本。 避免信号干扰 利用调制将信号抬到不同的通频带&#xff0c;可以有效避免信号频率交叠的相…

Unity制作背包的格子

1.新建一个面板 2.点击面板并添加这个组件 3.点击UI创建一个原始图像&#xff0c;这样我们就会发现图像出现在了面板的左上角。 4.多复制几个并改变 Grid Layout Group的参数就可以实现下面的效果了

汽车信息安全硬件讨论:SE vs HSM

目录 1.什么是Secure Element 2.芯片内置HSM和SE 3.未来HSM的发展 现在的智能网联汽车看起来像是一个连接万物的智能移动终端&#xff0c;它不仅可以与OEM云服务器通信接收OTA推送&#xff0c;还可以与手机蓝牙、Wifi交互完成远程汽车解锁、座舱内环境设置等等&#xff0c;借…