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 = true
    
    var 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 = true
    
    var 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)
                }
            }

            // 更多的 TabSections

            Tab(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 = true
    
    var 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 样式以及其它有趣的新特性。

感谢观赏,再会!😎

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

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

相关文章

技术性屏蔽百度爬虫已经一周了!

很久前明月就发现百度爬虫只抓取、只收录就是不给流量了,加上百度搜索体验越来越差,反正明月已经很久没有用过百度搜索,目前使用的浏览器几乎默认搜索都已经修改成其他搜索引擎了,真要搜索什么,一般都是必应谷歌结合着…

自然语言处理领域的明星项目推荐:Hugging Face Transformers

在当今人工智能与大数据飞速发展的时代,自然语言处理(NLP)已成为推动科技进步的重要力量。而在NLP领域,Hugging Face Transformers无疑是一个备受瞩目的开源项目。本文将从项目介绍、代码解释以及技术特点等角度,为您深…

python3GUI--ktv点歌软件By:PyQt5(附下载地址)

文章目录 一.前言二.展示1.启动2.搜索2.服务1.首页2.天气预报3.酒水饮料4.酒水饮料2 3.服务4.灯光5.调音6.排行榜7.分类点歌9.歌手点歌10.歌手个人页 三.心得体会1.关于代码2.关于设计3.关于打包 四.总结 文件大小:33.…

最新下载:XmanagerXShell【软件附加安装教程】

​相信大家都认同支持IPv6:最近越来越多的公司和国家都采用了IPv6,Xmanager的最新版本v5也加入支持这个功能,无论你是同时使用IPv4和IPv6网络或者完全的IPv6网络,Xmanager 5都可完全满足你的要求,使用MIT Kerberos认证…

理解什么是DSR,嗅探器视角下的IP和MAC地址识别(C/C++代码实现)

网络嗅探器是监控和分析网络流量的一种工具,它能够捕获数据包并提取出关键的信息,比如IP地址和MAC地址。 网络嗅探器工作原理基于网卡的工作模式。正常情况下,网卡只处理发送给它的数据包,忽略其他数据。但是,如果将网…

Python题目

实例 3.1 兔子繁殖问题(斐波那契数列) 兔子从出生后的第三个月开始,每月都会生一对兔子,小兔子成长到第三个月后也会生一对独自。初始有一对兔子,假如兔子都不死,那么计算并输出1-n个月兔子的数量 n int…

成章数据库安装体验

对标Redis的国产数据库 一位来自国产数据库的朋友想请我试用一下他们的产品。并且直言早期问题比较多,还请多多包涵。一般对于这种比较客观和友好的我都愿意试试。对于怼天怼地吊打谁的我个人就不尝试了。 他们中文名字叫“成章数据库“我就尝试从一个不了解产品的…

华为数通——OSPF

正掩码:/24 255.255.255.0 反掩码: 255.255.255.255 -255.-255.-255.0 0.0.0.255 例如掩码:255.255.252.0 反掩码:0.0.3.255 在反掩码里面,0 bit 表示精确匹配,1…

STM32上实现spwm调制原理分析

在STM32微控制器上实现SPWM(正弦脉宽调制,Sinusoidal Pulse Width Modulation)调制的核心是利用高频载波(三角波)与低频基波(正弦波)作比较得出。 那么在STM32里三角波和正弦波分别是什么&…

热电阻温度计的测量电路

热电阻温度计的测量电路,为达到高精度测量,通常会采用电桥测量原理,并结合适当的热电阻类型和连接方式。 惠斯通电桥是用于测量一组电阻式元件阻值变化的电路。该电路具有两个并联电阻支路,充当激励电压 VEXCITATION 的分压器。每…

无霍尔BLDC驱动

目前主要的无霍尔控制方案是基于反电势检测信 息判断换相点,本文研究反电势在 PWM - OFF 点的检 测方案确定换相点。 1. 反电动势检测方案 BLDC 的模型做等效,将线圈阻抗看成是一个 线性电阻和一个储能电感的等效,其等效电路图如图 1所示。 电机三相绕组输出端电压的电压…

【Java】已解决java.io.UnsupportedEncodingException异常

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决java.io.UnsupportedEncodingException异常 在Java编程中,java.io.UnsupportedEncodingException异常通常发生在尝试使用java.nio.charset.Charset或者它的旧版本…

如何去除VisualStudioCode最新版本出现的两条横线

作为一个对频繁更新有些抗拒的人,我曾多次遇到在更新后出现莫名问题的情况。然而,由于最近一次更新已经有一段时间了,我觉得或许这次会带来一些更好的设计或其他改进。于是,我决定更新Visual Studio Code,并分享一下我…

R语言 | 绘制带P值的差异柱状图

原文链接:R语言 | 绘制带P值的差异柱状图 本期教程 小杜的生信笔记,自2021年11月开始做的知识分享,主要内容是R语言绘图教程、转录组上游分析、转录组下游分析等内容。凡是在社群同学,可免费获得自2021年11月份至今全部教程&…

CVE-2023-50563(sql延时注入)

简介 SEMCMS是一套支持多种语言的外贸网站内容管理系统(CMS)。SEMCMS v4.8版本存在SQLI,该漏洞源于SEMCMS_Function.php 中的 AID 参数包含 SQL 注入 过程 打开靶场 目录扫描,发现安装install目录,进入,…

2024全国各地高考录取分数线一览表(含一本、二本、专科)

2024年高考录取分数线陆续公布,上大学网(www.sdaxue.com)为大家整理全国31个省市高考录取分数线汇总,包括本科批、专科批和特殊类招生控制分数线汇总,来看看你的省份多少分能上大学吧。 一、2024年全国高考录取线一览表 1、宁夏 一本线&…

Adaboost集成学习 | Adaboost集成学习特征重要性分析(Python)

目录 效果一览基本介绍模型设计程序设计参考资料效果一览 基本介绍 Adaboost集成学习特征重要性分析(Python)Adaboost(自适应增强)是一种常用的集成学习方法,用于提高机器学习算法的准确性。它通过组合多个弱分类器来构建一个强分类器。在Adaboost中,每个弱分类器都被赋予…

利用ChatGPT辅助撰写课题申报书中的研究框架与内容设计全攻略指南

欢迎关注EssayBot,为大家带来最酷最有效的智能AI学术科研写作攻略。关于使用ChatGPT等AI学术科研的相关问题可以和作者七哥沟通:yida985 撰写课题申报书是启动科研项目的第一个步骤,而研究框架与内容设计又是这一过程中的关键要素&#xff0…

探索FlowUs息流:个人和团队知识管理稳定解决方案|FlowUs稳定保障你的笔记安全无忧

FlowUs息流:稳定运营保障你的笔记安全无忧 在知识管理工具的选择上,稳定性是用户最关心的问题之一。FlowUs息流以其稳定的运营记录,为用户提供了一个可靠的工作环境。我们深知,一个知识管理平台的稳定性直接影响到团队的生产力和…

LoRaWAN网关源代码分析(基础概念篇)

目录 一、简介 1、lora_gateway 2、packet_forwarder 二、目录结构 1、lora_gateway 2、packet_forwarder 一、简介 LoRaWAN网关的实现主要依赖两个源代码:lora_gateway和packet_forwarder。接下来,我们将从分析源代码入手,移植LoRaWAN源…