SwiftUI之深入解析如何使用visualEffect视图修饰符

一、visualEffect 简介

  • 在 WWDC 23 中,SwiftUI 引入了一个名为 visualEffect 的新视图修饰符,此修饰符允许通过访问特定视图的布局信息来附加一组可动画化的视觉效果。那么,如何在 SwiftUI 中使用新的 visualEffect 视图修饰符呢?
  • 首先看一下,visualEffect 视图修饰符的最简单示例:
rust 复制代码
struct ContentView: View {
    var body: some View {
        Text("Hello World!")
            .visualEffect { initial, geometry in
                initial.offset(geometry.size)
            }
    }
}
  • 正如在上面的示例中所看到的,定义了一个文本视图并附加了 visualEffect 视图修饰符,每当附加 visualEffect 视图修饰符时,应该指定效果闭包,这是应用所有需要的效果的地方。
  • 效果闭包提供了两个参数:第一个是附加到视图的效果集合的初始状态,它是 EmptyVisualEffect 类型的实例,使用此实例来附加额外的效果;第二个参数是包含视图的所有布局信息的 GeometryProxy 类型的实例,比如 frame、安全区域等。

二、什么是视觉效果?

  • 视觉效果是可以改变视图的视觉外观但不影响其布局的任何东西。在 SwiftUI 框架的先前版本中,有视图修饰符,如缩放、偏移、模糊、对比度、饱和度、不透明度、旋转等,它们全部都是视觉效果,并且现在符合 VisualEffect 协议,当然可以在 visualEffect 闭包中使用其中任何一个。
rust 复制代码
struct ContentView: View {
    
    var body: some View {
        Text("Hello World!")
            .visualEffect { initial, geometry in
                initial
                    .blur(radius: 8)
                    .opacity(0.9)
                    .scaleEffect(.init(width: 2, height: 2))
            }
    }
}
  • 像 frame 和 padding 这样的东西不是视觉效果,不能在 visualEffect 闭包中使用它们,因为它们修改了视图层次结构的布局。

三、visualEffect 修饰符视觉效果

  • visualEffect 视图修饰符是完成旧事物的新方法,可以使用旧视图修饰符修改视图的不透明度和偏移。如果不需要布局信息,可以继续使用它们,新方法的唯一区别是通过从 GeometryProxy 提供的布局信息计算视图的视觉效果的方式来限定视图的视觉效果。
  • visualEffect 视图修饰符支持可动画化的值,因此可以继续使用它根据视图在视图层次结构中的框架和边界来动画化视图的视觉外观。
rust 复制代码
struct ContentView: View {
    @State private var isScaled = false
    
    var body: some View {
        VStack {
            Button("Scale") {
                isScaled.toggle()
            }
            
            Text("Hello World!")
                .visualEffect { initial, geometry in
                    initial.scaleEffect(
                        CGSize(
                            width: isScaled ? 2 : 1,
                            height: isScaled ? 2 : 1
                        )
                    )
                }
                .animation(.smooth, value: isScaled)
        }
    }
}

四、完整示例

  • 将如下的代码放入 Swift 文件中,然后在 Xcode 中打开并运行,选择合适的模拟器。请注意,由于视觉效果和动画效果,最好在模拟器上查看效果。
rust 复制代码
import SwiftUI

struct ContentView: View {
    var body: some View {
        Text("Hello World!")
            .visualEffect { initial, geometry in
                initial.offset(geometry.size)
            }
    }
}

struct ContentViewWithEffects: View {
    var body: some View {
        Text("Hello World!")
            .visualEffect { initial, geometry in
                initial
                    .blur(radius: 8)
                    .opacity(0.9)
                    .scaleEffect(.init(width: 2, height: 2))
            }
    }
}

struct ContentViewWithAnimation: View {
    @State private var isScaled = false
    
    var body: some View {
        VStack {
            Button("Scale") {
                isScaled.toggle()
            }
            
            Text("Hello World!")
                .visualEffect { initial, geometry in
                    initial.scaleEffect(
                        CGSize(
                            width: isScaled ? 2 : 1,
                            height: isScaled ? 2 : 1
                        )
                    )
                }
                .animation(.smooth, value: isScaled)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
        ContentViewWithEffects()
        ContentViewWithAnimation()
    }
}
相关推荐
东坡肘子6 天前
谁是 AI-relay App 的真正威胁 -- 肘子的 Swift 周报 #158
人工智能·swiftui·swift
东坡肘子13 天前
当 Build in Public 重新转入地下 -- 肘子的 Swift 周报 #157
人工智能·swiftui·swift
OliverQiu13 天前
开源一个 macOS 小工具:集中管理 ChatGPT 的网络启动配置
macos·chatgpt·swiftui·mac·proxy·codex·dmg
传奇开心果编程17 天前
【SwiftUI提高练中学】第9课 安全与隐私
swiftui·移动开发·swift·编程语言理论·开发范式·编程框架·声明式ui
传奇开心果编程18 天前
【声明式UI开发实用技术学与练】第8课 状态提升与下放
学习·flutter·react native·ui·swiftui·composer
东坡肘子18 天前
Swift Server,又多了一个 Google -- 肘子的 Swift 周报 #156
人工智能·swiftui·swift
传奇开心果编程19 天前
【现代声明式UI学与练】第4课 列表渲染与 key——如何高效渲染列表、key 的作用、列表重排时的状态保持
学习·flutter·react native·ui·swiftui·android jetpack
传奇开心果编程19 天前
【SwiftUI提高练中学】第8课 网络层架构:拦截器、重试、缓存与离线优先
学习·macos·ui·ios·swiftui
传奇开心果编程19 天前
【现代声明式UI学与练】第7课 组件通信——父传子、子传父、跨层级通信、状态提升与 Context
学习·flutter·react native·ui·swiftui·android jetpack
tink20 天前
告别 Xcode IDE:用 VS Code + SweetPad + XcodeGen 开发 iOS 应用的完整指南
ios·swiftui·xcode