iOS 17 之后,SwiftUI 迎来了一个非常关键但又容易被低估的 API ------
.visualEffect。如果你曾经在
ScrollView里被GeometryReader折磨过,那这篇文章基本可以当作你的"解放指南"。
一、.visualEffect 是什么?
一句话概括:
.visualEffect是一个"不参与布局、只在最终渲染阶段生效"的视觉修饰器。
它允许你:
- 拿到视图在屏幕中的真实几何位置
- 根据滚动位置 / 距离中心点 / 是否即将离屏
- 对视图做 缩放、模糊、位移、透明度 等视觉变化
👉 非常适合用来实现 系统级滚动动效。
二、API 结构与核心签名
swift
.visualEffect { content, geometryProxy in
content
}
参数说明:
content:原始 ViewgeometryProxy:视图最终渲染后的几何信息- 返回值:一个新的 View(只影响视觉,不影响布局)
三、为什么它能"替代" GeometryReader?
1️⃣ 传统 GeometryReader 的问题
swift
GeometryReader { geo in
let y = geo.frame(in: .global).minY
Text("Hello")
}
.frame(height: 100)
常见问题:
- 会参与布局,影响父视图尺寸
- 在
ScrollView中容易引发布局异常 - 性能与可维护性都不理想
2️⃣ .visualEffect 的优势
| 对比项 | GeometryReader | visualEffect |
|---|---|---|
| 是否参与布局 | ✅ 是 | ❌ 否 |
| 是否影响尺寸 | 会 | 不会 |
| 滚动性能 | 一般 | 很好 |
| 系统推荐 | ❌ | ✅ |
结论:能用
.visualEffect的地方,基本不该再用 GeometryReader。
四、Demo 1:滚动缩放(最经典)
效果
- Cell 越靠近屏幕中心 → 越大
- 离中心越远 → 缩小
示例代码
swift
ScrollView {
VStack(spacing: 40) {
ForEach(0..<20) { index in
Text("Item (index)")
.font(.largeTitle)
.frame(maxWidth: .infinity)
.padding()
.background(.blue.opacity(0.2))
.visualEffect { content, geo in
let minY = geo.frame(in: .global).minY
let scale = max(0.85, 1 - abs(minY) / 1000)
return content.scaleEffect(scale)
}
}
}
}
五、Demo 2:滚动模糊(系统级质感)
使用场景
- 卡片列表
- 背景元素
- 音乐 / 专辑封面
swift
.visualEffect { content, geo in
let y = geo.frame(in: .scrollView).minY
let blur = min(abs(y) / 40, 12)
return content.blur(radius: blur)
}
六、Demo 3:视差位移(Parallax)
swift
.visualEffect { content, geo in
let y = geo.frame(in: .global).minY
content.offset(y: -y * 0.2)
}
常见于:
- Banner
- 大图 Header
- Apple Music / App Store 首页
七、Demo 4:缩放 + 透明度(App Store 风格)
swift
.visualEffect { content, geo in
let frame = geo.frame(in: .scrollView)
let distance = abs(frame.midY - 300)
let scale = max(0.85, 1 - distance / 1000)
return content
.scaleEffect(scale)
.opacity(scale)
}
八、.visualEffect vs .scrollTransition
swift
.scrollTransition { content, phase in
content.scaleEffect(phase.isIdentity ? 1 : 0.9)
}
| 对比项 | visualEffect | scrollTransition |
|---|---|---|
| 几何自由度 | ⭐⭐⭐⭐⭐ | ⭐⭐ |
| API 简洁度 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 是否仅限滚动 | ❌ | ✅ |
scrollTransition是封装好的方案,visualEffect是底层利器。
九、使用时的注意事项
1️⃣ 只做"视觉处理"
不要在 .visualEffect 中:
- 修改状态
- 触发网络请求
- 写业务逻辑
2️⃣ 坐标空间要选对
csharp
.global // 全局屏幕
.scrollView // 推荐:滚动容器
.local // 本地
👉 滚动相关效果,优先使用 .scrollView
十、总结
SwiftUI 布局完成 →
.visualEffect介入 → 最终视觉变换
你可以把它理解为:
"官方支持、不破坏布局的 GeometryReader + Transform"
如果你觉得这篇文章有帮助
欢迎 👍 / 收藏 / 评论交流