当前位置: 首页 > news >正文

SwiftUI 5.0(iOS 17)进一步定制 TipKit 外观让撸码如虎添翼

在这里插入图片描述

概览

在之前 SwiftUI 5.0(iOS 17)TipKit 让用户更懂你的 App 这篇博文里,我们已经初步介绍过了 TipKit 的基本知识。

在这里插入图片描述

现在,让我们来看看如何进一步利用 SwiftUI 对 TipKit 提供的细粒度外观定制技巧,让 Tip 更加“明眸皓齿”。

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

  • 概览
  • 1. TipKit 温故而知新
  • 2. Tip 外观细粒度定制
  • 3. 完全自己打造 Tip 外观
  • 总结

相信学完本课后,小伙伴们对 TipKit 的内功修为会更加炉火纯青、登峰造极!

那还等什么呢?Let’s go!!!😉


本文对应的视频课在此,欢迎小伙伴们恣意观赏!

SwiftUI 定制 TipKit 外观进一步让撸码如虎添翼


1. TipKit 温故而知新

在前一篇关于 TipKit 的博文中,我们介绍了什么是 TipKit 以及如何在 App 中支持 TipKit 的方法。

这里再回忆一下:创建一个 Tip 很简单,我们只需让类型遵守 Tip 协议即可。

struct FavoriteTip: Tip {var title: Text {Text("收藏最爱的图片").bold()}var message: Text? {Text("将心仪的图片保存到相册中").font(.headline).foregroundStyle(.gray.gradient)}var image: Image? {Image(systemName: "heart")}
}

然后,我们可以通过嵌入和弹出两种不同方法来显示它:

// 嵌入 Tip
struct ContentView: View {let favTip = FavoriteTip()var body: some View {NavigationStack {VStack {TipView(favTip)}.padding().navigationTitle("TitKit演示")}}
}// 弹出 Tip
struct ContentView: View {let favTip = FavoriteTip()var body: some View {NavigationStack {VStack {...}.padding().navigationTitle("TitKit演示").toolbar {ToolbarItem {Image(systemName: "heart").font(.title.weight(.black)).foregroundStyle(.pink.gradient).popoverTip(favTip, arrowEdge: .top)}}}}
}

嵌入和弹出 Tip 的效果如下图所示:

嵌入 Tip

弹出 Tip

如果大家对于默认 Tip 的外观不甚满意怎么办?别急,SwiftUI 还有“妙计”。

2. Tip 外观细粒度定制

Apple 在推出 TipKit 框架的同时也提供了若干修改器方法,我们可以利用它们来进一步调整 Tip 视图的外观。

首先是 tipCornerRadius() 方法,它可以用来调整 Tip 视图边角的弧度:

struct ContentView: View {let favTip = FavoriteTip()@State var addTipRadius = falsevar body: some View {NavigationStack {VStack {TipView(favTip)Toggle(isOn: $addTipRadius) {Text("增加 Tip 边角弧度").font(.title3)}}.padding().navigationTitle("TitKit演示").tipCornerRadius(addTipRadius ? 30 : 10).frame(maxHeight: .infinity).background(.gray.opacity(0.66).gradient).animation(.bouncy, value: addTipRadius)}}
}

值得注意的是:tipCornerRadius 修改器方法和随后介绍的所有 Tip 外观调整方法都会沿着视图继承树向下传递,这意味着顶层的方法会影响内部所有的 Tip 外观。

在这里插入图片描述

接下来是 tipImageSize() 修改器,我们可以用它来调整 Tip 内部图片的尺寸:

NavigationStack {VStack {TipView(favTip)}.tipImageSize(CGSize(width: incImageSize ? 50 : 24, height: incImageSize ? 50 : 24)).frame(maxHeight: .infinity).background(.gray.opacity(0.66).gradient).animation(.bouncy, value: incImageSize)
}

运行效果如下所示:

在这里插入图片描述

最后,我们可以用 tipBackground() 修改器方法来调整 Tip 视图背景的显示样式:

NavigationStack {VStack {TipView(favTip)}.tipBackground(incBackgroundHue ? Material.ultraThick : .thin).frame(maxHeight: .infinity).background(.gray.opacity(0.66).gradient).animation(.bouncy, value: incImageSize)
}

运行的效果不出意料:

在这里插入图片描述

上面我们介绍了一些从宏观上调整 Tip 外观的方法,如果小伙伴们还是觉得捉襟见肘、鸟入樊笼怎么办?

别急,我们还可以“欲穷千里目,更上一层楼”:自己动手“丰衣足食”来 100% “恣意”决定 Tip 该如何显示。

3. 完全自己打造 Tip 外观

为了最大程度满足秃头码农们随心所欲定制 Tip 外观的需求,苹果决定将 Tip 的外观样式化(Styling)以便让我们可以无拘无束定制它们“主题皮肤”。

经常撸 SwiftUI 代码的小伙伴们都知道,在 SwiftUI 中大部分原生视图都有对应的样式(Style),比如按钮、Label、Toggle 等等。视图样式为我们充分定制视图的外观带来了极大的便利。

TipKit 也不例外,我们同样可以利用 tipViewStyle() 修改器来排忧解难:

在这里插入图片描述

为了能够安闲自在的 100% 纯手工打造 Tip 的外观,我们首先需要“由着性子”创建一个遵守 TipViewStyle 协议的类型:

struct PureCustomTipViewStyle: TipViewStyle {func makeBody(configuration: Configuration) -> some View {VStack(alignment: .leading) {HStack(alignment: .bottom) {if let image = configuration.image {image.resizable().aspectRatio(contentMode: .fit).font(.title.weight(.heavy)).frame(width: 25, height: 25).foregroundStyle(.teal).padding().overlay {RoundedRectangle(cornerRadius: 15.0).stroke(.secondary, lineWidth: 3.0)}}Rectangle().frame(width: 3, height: 100).foregroundStyle(.white.gradient)VStack(alignment: .leading) {if let title = configuration.title {title.font(.headline)}if let message = configuration.message {Group {message.font(.subheadline).padding()}.background {RoundedRectangle(cornerRadius: 15.0).foregroundStyle(Material.thin)}}}}HStack {Spacer()ForEach(configuration.actions, id: \.id) { action inButton {action.handler()} label: {Image(systemName: "volleyball.fill").foregroundStyle(.yellow.gradient)action.label()}.fontWeight(.bold).buttonStyle(.borderedProminent)}}}.padding().background {Image("bg").resizable().opacity(0.77)}}
}

接着,为了方便起见我们还可以将上面创建的 Tip 自定义样式融入到 TipViewStyle 自身中去:

extension TipViewStyle where Self == PureCustomTipViewStyle {static var pureCustom: Self {Self.init()}
}

最后在 Tip 视图本身或其上层容器中,我们即可悠然自得的调用 tipViewStyle() 修改器方法来施展改头换面的“黑魔法”啦:

struct ContentView: View {let favTip = FavoriteTip()@State var addTipRadius = false@State var incImageSize = false@State var incBackgroundHue = falsevar body: some View {NavigationStack {VStack {TipView(favTip)Toggle(isOn: $addTipRadius) {Text("增加 Tip 边角弧度").font(.title3)}Toggle(isOn: $incImageSize) {Text("增加 Tip 图片大小").font(.title3)}Toggle(isOn: $incBackgroundHue) {Text("增加 Tip 背景色度").font(.title3)}}.padding().navigationTitle("TitKit演示").tipCornerRadius(addTipRadius ? 30 : 10).tipImageSize(CGSize(width: incImageSize ? 50 : 24, height: incImageSize ? 50 : 24)).tipBackground(incBackgroundHue ? Material.ultraThick : .thin)// 应用我们的自定义 Tip 样式.tipViewStyle(.pureCustom).frame(maxHeight: .infinity).background(.gray.opacity(0.66).gradient).animation(.bouncy, value: addTipRadius).animation(.bouncy, value: incImageSize).animation(.bouncy, value: incBackgroundHue)}}
}

编译运行代码,现在用全身毛孔来感受一下纯手工打造 Tip 界面的愉悦之美吧!

在这里插入图片描述

至此,我们完全掌握了 TipKit 中外观调整与定制的全部技巧,小伙伴们还不赶快发挥天马行空般的想象力打造自己的 Tip 视图吧!棒棒哒!💯


想要系统学习 Swift 语言的小伙伴们,千万不要错过我的《Swift 语言开发精讲》专栏哦,欢迎大家恣意观赏:

在这里插入图片描述

  • Swift 语言开发精讲

总结

在本篇博文中,我们介绍了 SwiftUI 5.0 中从宏观全局调整 Tip 视图显示的几种方式。如果小伙伴们觉得还是不能放开手脚,我们还探讨了如何 100% 纯手工打造自己 Tip 内部布局的方法,包您满意!

感谢观赏,再会!😎

相关文章:

SwiftUI 5.0(iOS 17)进一步定制 TipKit 外观让撸码如虎添翼

概览 在之前 SwiftUI 5.0(iOS 17)TipKit 让用户更懂你的 App 这篇博文里,我们已经初步介绍过了 TipKit 的基本知识。 现在,让我们来看看如何进一步利用 SwiftUI 对 TipKit 提供的细粒度外观定制技巧,让 Tip 更加“明眸…...

使用C#实现VS窗体应用——画图板

✅作者简介:大家好,我是 Meteors., 向往着更加简洁高效的代码写法与编程方式,持续分享Java技术内容。🍎个人主页:Meteors.的博客💞当前专栏:小项目✨特色专栏: 知识分享&#x1f96d…...

flutter 自定义本地化-GlobalMaterialLocalizations(重写本地化日期转换)

1. 创建自定义 GlobalMaterialLocalizations import package:flutter_localizations/flutter_localizations.dart; import package:kittlenapp/utils/base/date_time_util.dart;///[auth] kittlen ///[createTime] 2024-05-31 11:40 ///[description]class MyMaterialLocaliza…...

HTTPS 原理技术

HTTPS原理技术 背景简介原理总结 背景 随着年龄的增长,很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来,技术出身的人总是很难放下一些执念,遂将这些知识整理成文,以纪念曾经努力学习奋斗的日子。本文内容并非完全原创&am…...

Linux基础指令及其作用之压缩与解压

压缩与解压targzip示例输出解释 gunzipzipunzip 压缩与解压 tar tar xzf 是一个常用的命令组合,用于解压缩由 gzip 压缩的 tarball 文件。下面是对这个命令的详细说明: tar:这是一个用于在 Linux 和类 Unix 系统上创建、查看或提取归档文件…...

ORA-08189: 因为未启用行移动功能, 不能闪回表问题

在执行闪回恢复误删数据出现“ORA-08189: 因为未启用行移动功能, 不能闪回表”的错误提示。 ORA-08189 错误表示你尝试对一个表执行闪回操作,但该表没有启用行移动(ROW MOVEMENT)功能。行移动是Oracle中的一个特性,它允许表中的行…...

html+CSS部分基础运用9

项目1 参会注册表 1.设计参会注册表页面,效果如图9-1所示。 图9-1 参会注册表页面 项目2 设计《大学生暑期社会实践调查问卷》 1.设计“大学生暑期社会实践调查问卷”页面,如图9-2所示。 图9-2 大学生暑期社会调查表页面 2.调查表前导语的…...

五大元素之一,累不累——Java内部类

目录 简略版: 详解版: 使用场景: 内部类的优点: 内部类的分类: 一. 成员内部类 1.创建对象 2.访问方法 3. 外部类名.this. 二. 静态内部类 1. 创建对象 2. 访问特点 三. 局部内部类 四. 匿名内部类 …...

YAML快速编写示例

一、案例 1.1 自主式创建service关联上方的pod 资源名称my-nginx-kkk命名空间my-kkk容器镜像nginx:1.21容器端口80标签njzb:my-kkk 1.1.1 创建一个demo文件夹 1.1.2 创建并获取模版文件 1.1.3 查看服务并编写yaml文件 1.1.4 编写yaml文件并部署,查看服务是否运行成…...

2024 江苏省大学生程序设计大赛 2024 Jiangsu Collegiate Programming Contest(FGKI)

题目来源:https://codeforces.com/gym/105161 文章目录 F - Download Speed Monitor题意思路编程 G - Download Time Monitor题意思路编程 K - Number Deletion Game题意思路编程 I - Integer Reaction题意思路编程 写在前面:今天打的训练赛打的很水&…...

【C语言】基于C语言实现的贪吃蛇游戏

【C语言】基于C语言实现的贪吃蛇游戏 🔥个人主页:大白的编程日记 🔥专栏:C语言学习之路 文章目录 【C语言】基于C语言实现的贪吃蛇游戏前言一.最终实现效果一.Win32 API介绍1.1Win32 API1.2控制台程序1.3控制台屏幕上的坐标COORD…...

代码审计(工具Fortify 、Seay审计系统安装及漏洞验证)

源代码审计 代码安全测试简介 代码安全测试是从安全的角度对代码进行的安全测试评估。(白盒测试;可看到源代码) 结合丰富的安全知识、编程经验、测试技术,利用静态分析和人工审核的方法寻找代码在架构和编码上的安全缺陷&#xf…...

cocos creator 3.x 手搓背包拖拽装备

项目背景: 游戏背包 需要手动 拖拽游戏装备到 装备卡槽中,看了下网上资料很少。手搓了一个下午搞定,现在来记录下实现步骤; 功能拆分: 一个完整需求,我们一般会把它拆分成 几个小步骤分别造零件。等都造好了…...

运维开发.Kubernetes探针与应用

运维系列 Kubernetes探针与应用 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite:http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/qq_28550263…...

Spring 框架:Java 企业级开发的基石

文章目录 序言Spring 框架的核心概念Spring 框架的主要模块Spring Boot:简化 Spring 开发Spring Cloud:构建微服务架构实际案例分析结论 序言 Spring 框架自 2002 年发布以来,已经成为 Java 企业级开发的标准之一。它通过提供全面的基础设施…...

在Docker中使用GPU

一、安装nvidia-container-toolkit 总之一句话:nvidia-docker和nvidia-docker2,nvidia-container-runtime 已经被英伟达迭代了,可以认为nvidia-container-toolkit是nvidia-docker和nvidia-docker2, nvidia-container-runtime 的替…...

vue3 前端实现导出下载pdf文件

这样的数据实现导出 yourArrayBufferOrByteArray 就是后端返回数据 // 创建Blob对象const blob new Blob([new Uint8Array(res)], { type: application/pdf })// 创建一个表示该Blob的URLconst url URL.createObjectURL(blob);// 创建一个a标签用于下载const a document.cr…...

AI智能体研发之路-模型篇(五):pytorch vs tensorflow框架DNN网络结构源码级对比

博客导读: 《AI—工程篇》 AI智能体研发之路-工程篇(一):Docker助力AI智能体开发提效 AI智能体研发之路-工程篇(二):Dify智能体开发平台一键部署 AI智能体研发之路-工程篇(三&am…...

电商物流查询解决方案助力提升消费者体验

截至2023年12月,中国网络购物用户规模达9.15亿人,占网民整体的83.8%。这一庞大的数字不仅展现了电子商务的蓬勃发展,也标志着数字零售企业营销战略的转变——从以产品和流量为核心,到用户为王的新阶段。因此,提升消费者…...

【深度密码】神经网络算法在机器学习中的前沿探索

目录 🚝前言 🚍什么是机器学习 1. 基本概念 2. 类型 3. 关键算法 4. 应用领域 5. 工作流程 🚋什么是神经网络 基本结构 🚂神经网络的工作原理 前向传播(Forward Propagation): 损失函…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...

三体问题详解

从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版

7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...

快刀集(1): 一刀斩断视频片头广告

一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...

Spring Security 认证流程——补充

一、认证流程概述 Spring Security 的认证流程基于 过滤器链(Filter Chain),核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤: 用户提交登录请求拦…...

comfyui 工作流中 图生视频 如何增加视频的长度到5秒

comfyUI 工作流怎么可以生成更长的视频。除了硬件显存要求之外还有别的方法吗? 在ComfyUI中实现图生视频并延长到5秒,需要结合多个扩展和技巧。以下是完整解决方案: 核心工作流配置(24fps下5秒120帧) #mermaid-svg-yP…...

【向量库】Weaviate概述与架构解析

文章目录 一、什么是weaviate二、High-Level Architecture1. Core Components2. Storage Layer3. 组件交互流程 三、核心组件1. API Layer2. Schema Management3. Vector Indexing3.1. 查询原理3.2. 左侧:Search Process(搜索流程)3.3. 右侧&…...

【web笔记】JavaScript实现有动画效果的进度条

文章目录 1 实现效果2 实现代码 1 实现效果 2 实现代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"utf-8"><style>#progress {width: 300px;height: 20px;border-radius: 0; /* 移除圆角 */-webkit-appearance…...

PySide6 GUI 学习笔记——常用类及控件使用方法(多行文本控件QTextEdit)

文章目录 PySide6.QtWidgets.QTextEdit 应用举例概述核心特性常用方法文本内容操作光标和选择操作格式和样式查找功能视图控制状态设置常用信号 代码示例示例说明1. 基本设置2. 文本格式化功能3. 功能按钮4. 信号处理 PySide6.QtWidgets.QTextEdit 应用举例 概述 QTextEdit 是…...