
概述
各位微秃小码农们是否已经厌倦了 SwiftUI 中千篇一律、愣头愣脑的 sheet 弹窗动画?我们能否换一个范儿来弹出窗口呢?

答案是肯定!不仅可以,而且还很容易呢!
在本篇博文中,您将学到如下内容:
概述
- 旧式转场的"尴尬"
- SwiftUI 新转场范式 总结
小伙伴们无需彷徨等待,让我们马上开始 SwiftUI 弹框转场动画的冒险之旅吧! Let's go!!!;)
1. 旧式转场的"尴尬"
在 SwiftUI 构建的 App 里,我们对于应用界面的总体架构来说有几种不同的组织方式。其中,弹出"模式视图"给人一种简单爽快的感觉,这是通过 sheet 修改器来实现的。
下面是通过 Cursor 提示词生成的 SheetContent 视图,用的是 chatGPT5 引擎:
swift
// Sheet 内容视图
struct SheetContent: View {
@Environment(\.dismiss) private var dismiss
var body: some View {
NavigationView {
VStack(spacing: 30) {
// 顶部图标 - 与源按钮匹配
Image(systemName: "plus.circle.fill")
.font(.system(size: 100))
.foregroundColor(.blue)
.padding(.top, 50)
Text("Zoom Transition 成功!")
.font(.title)
.fontWeight(.bold)
Text("这个界面通过 Zoom 动画从底部按钮展开")
.font(.body)
.foregroundColor(.secondary)
.multilineTextAlignment(.center)
.padding(.horizontal)
// 示例内容
VStack(spacing: 16) {
HStack {
Image(systemName: "checkmark.circle.fill")
.foregroundColor(.green)
Text("动画效果流畅")
Spacer()
}
.padding()
.background(Color.green.opacity(0.1))
.cornerRadius(10)
HStack {
Image(systemName: "arrow.up.circle.fill")
.foregroundColor(.blue)
Text("从源元素展开")
Spacer()
}
.padding()
.background(Color.blue.opacity(0.1))
.cornerRadius(10)
}
.padding(.horizontal)
Spacer()
// 关闭按钮
Button("关闭") {
dismiss()
}
.font(.title2)
.foregroundColor(.white)
.padding()
.background(Color.blue)
.cornerRadius(10)
.padding(.bottom, 50)
}
.navigationTitle("详情")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("完成") {
dismiss()
}
}
}
}
}
}
生成的界面如下所示:

看起来 AI 生成的代码还不错吧?
接下来,再由 chatGPT 5 大脑来搞定我们的主视图:
swift
// 主内容视图
struct MainView: View {
var body: some View {
NavigationView {
VStack(spacing: 20) {
Text("Zoom Transition 演示")
.font(.largeTitle)
.fontWeight(.bold)
Text("点击底部的加号按钮")
.font(.title2)
.foregroundColor(.secondary)
Spacer()
// 一些示例内容
VStack(spacing: 16) {
HStack {
Image(systemName: "star.fill")
.foregroundColor(.yellow)
Text("这是一个示例界面")
Spacer()
}
.padding()
.background(Color.gray.opacity(0.1))
.cornerRadius(10)
HStack {
Image(systemName: "heart.fill")
.foregroundColor(.red)
Text("点击底部按钮查看 Zoom 效果")
Spacer()
}
.padding()
.background(Color.gray.opacity(0.1))
.cornerRadius(10)
}
.padding(.horizontal)
Spacer()
}
.navigationTitle("主界面")
}
}
}
最后,同样让 AI 操刀生成 ZoomTransitionDemo 视图,它将会是 sheet 弹窗的绝对主宰(驱动器):
swift
// Zoom transition 演示
struct ZoomTransitionDemo: View {
// 控制 sheet 的显示状态
@State private var isPresentedNoAnim = false
var body: some View {
MainView()
.safeAreaInset(edge: .bottom) {
HStack {
Button(action: {
isPresentedNoAnim = true
}) {
VStack(spacing: 10) {
Text("旧式转场")
Image(systemName: "plus.circle.fill")
.font(.largeTitle.weight(.black))
}
.font(.title3.bold())
.foregroundStyle(.red.gradient)
}
}
}
.sheet(isPresented: $isPresentedNoAnim) {
SheetContent()
}
}
}
现在,点击我们示例 App 主界面底部的 + 按钮,即可 sheet 蹦出急不可耐的小视图了:

不过,这种 sheet 弹出视图的转场方式貌似有点"腻歪",它太其貌不扬,我们甚至有些审美疲劳了。
还好,Apple 及时为我们提供了全新的弹窗丝滑过渡方式,无需增加繁琐的撸码,我们即可实现漂亮的转场效果。
2. SwiftUI 新转场范式
从 iOS 18(SwiftUI 6.0)开始,苹果为导航转场增加了全新的 navigationTransition 修改器方法,它的功用很简单------设置视图导航的转场样式: 
除此之外,我们还需要在导航的源视图上使用 matchedTransitionSource 修改器方法才能确保"如鱼得水":
让我们利用上面两个修改器方法,将 ZoomTransitionDemo 视图的原代码进行些许修改:
swift
struct ZoomTransitionDemo: View {
// 用于定义共享坐标空间的命名空间
@Namespace private var namespace
// 控制 sheet 的显示状态
@State private var isPresented = false
var body: some View {
MainView()
.safeAreaInset(edge: .bottom) {
HStack {
Button(action: {
isPresented = true
}) {
VStack(spacing: 10) {
Text("顺滑转场")
Image(systemName: "plus.circle.fill")
.font(.largeTitle.weight(.black))
}
.font(.title3.bold())
.foregroundStyle(.blue.gradient)
}
.matchedTransitionSource(id: "transition-id", in: namespace)
.padding(.trailing)
}
}
.sheet(isPresented: $isPresented) {
SheetContent()
.navigationTransition(.zoom(sourceID: "transition-id", in: namespace))
}
}
}
看到了吗?我们只是在原来主视图的弹出视图和源视图上增加了对应的视图修改器方法即可大功告成!
现在,欣赏一下全新的弹窗转场动画,小伙伴们是否爱了爱了呢?❤️
棒棒哒!💯

总结
在本篇博文中,我们讨论了如何在 iOS 18+(SwiftUI 6)中仅用寥寥几行代码就让 sheet 弹窗转场动画有了焕然一新的进化,不禁让人眼前一亮!
感谢观赏,我们再会啦!8-)