在 SwiftUI 中的作用域动画
创始人
2024-09-25 11:50:54
0

在这里插入图片描述

在这里插入图片描述

文章目录

    • 前言
    • 简单示例
    • 动画视图修饰符
    • 使用多个可动画属性
    • 使用 ViewBuilder
    • 总结

前言

从一开始,动画就是 SwiftUI 最强大的功能之一。你可以在 SwiftUI 中快速构建流畅的动画。唯一的缺点是每当我们需要运行多步动画或将动画范围限定到视图层次结构的特定部分时,我们如何控制动画。

简单示例

让我们从一个简单的示例开始,展示我们旧方法的一些缺点,这些方法用于在 SwiftUI 中驱动动画。

struct ContentView: View {     @State private var isHidden = false          var body: some View {         VStack {             Button("Animate") {                 isHidden.toggle()             }                          HugeView()                 .opacity(isHidden ? 0.0 : 1.0)                              AnotherHugeView()         }         .animation(.default)     } } 

如上例所示,我们有一个包含按钮和两个视图的视图层次结构,这些视图放置在垂直堆栈中。我们将动画视图修饰符附加到整个堆栈,以动画堆栈内的任何更改。

当我们按下按钮时,堆栈会动画显示内部的任何更改。但是,动画视图修饰符不连接到 isHidden 属性,这意味着它将动画显示可能发生的任何更改。其中一些更改可能是意外的,比如环境值的变化。

动画视图修饰符

我们可以通过使用动画视图修饰符的另一个版本来消除意外动画,在这个版本中,我们可以绑定到特定值,并且仅在值更改时进行动画处理。

struct ContentView: View {     @State private var isHidden = false          var body: some View {         VStack {             Button("Animate") {                 isHidden.toggle()             }                          HugeView()                 .opacity(isHidden ? 0.0 : 1.0)                          AnotherHugeView()         }         .animation(.default, value: isHidden)     } } 

在上面的示例中,我们使用了带有 value 参数的动画视图修饰符。它允许我们将动画范围限定为单个值,并仅在与特定值相关的更改时执行动画。在这种情况下,我们没有任何意外的动画。

使用多个可动画属性

如果我们有多个可动画属性怎么办?

在这种情况下,我们必须为每个可动画属性附加一个动画修饰符。这个解决方案非常有效,但在人体工程学方面有一个缺点。

struct ContentView: View {     @State private var firstStep = false     @State private var secondStep = false          var body: some View {         VStack {             Button("Animate") {                 Task {                     firstStep.toggle()                     try? await Task.sleep(nanoseconds: 3_000_000_000)                     secondStep.toggle()                 }             }                          // 其他视图在这里                          SomeView()                 .opacity(firstStep ? 1.0 : 0.0)                 .blur(radius: secondStep ? 0 : 20.0)         }         .animation(.default, value: firstStep)         .animation(.default, value: secondStep)     } } 

幸运的是,SwiftUI 引入了动画视图修饰符的一个新变体,允许我们使用 ViewBuilder 闭包来限定动画的范围。

struct ContentView: View {     @State private var firstStep = false     @State private var secondStep = false          var body: some View {         VStack {             Button("Animate") {                 Task {                     firstStep.toggle()                     try? await Task.sleep(nanoseconds: 1_000_000_000)                     secondStep.toggle()                 }             }                          // 其他视图在这里                          SomeView()                 .animation(.default) { content in                     content                         .opacity(firstStep ? 1.0 : 0.0)                         .blur(radius: secondStep ? 0 : 20.0)                 }         }     } } 

如上例所示,我们使用动画视图修饰符,提供我们需要的动画类型和一个 ViewBuilder 闭包,在这个动画中应用。动画仅在提供的 ViewBuilder 闭包的上下文中工作,不会扩展到其他任何地方。

使用 ViewBuilder

作为起点,ViewBuilder 闭包提供一个参数,用于占位视图,在其中应用了动画视图修饰符。在 ViewBuilder 闭包内部,可以安全地对视图应用任何视图修饰符,并期望仅对此代码块进行动画处理。

struct ContentView: View {     @State private var firstStep = false     @State private var secondStep = false          var body: some View {         VStack {             Button("Animate") {                 Task {                     firstStep.toggle()                     try? await Task.sleep(nanoseconds: 1_000_000_000)                     secondStep.toggle()                 }             }                          // 其他视图在这里                          SomeView()                 .transaction { t in                     t.animation = t.animation?.speed(2)                 } body: { content in                     content                         .opacity(firstStep ? 1.0 : 0.0)                         .blur(radius: secondStep ? 0 : 20.0)                 }         }     } } 

正如你所看到的,SwiftUI 提供了一种类似的方法,以在视图层次结构中维护有作用域的事务。

总结

这篇文章介绍了在SwiftUI中构建动画的新方法,重点解决了在多步动画或特定视图层次结构中控制动画的挑战。通过引入带有value参数的动画修饰符,以及使用ViewBuilder闭包限定动画范围,作者展示了更精确和灵活的动画控制方式。

这种方法在处理多个可动画属性时尤其强大。文章还提到了SwiftUI引入的一项新变体,使用ViewBuilder闭包可在动画中应用视图修饰符,有效地将动画范围限定在特定的上下文中。

最后,介绍了在 SwiftUI 中构建有作用域的事务的新方法,以维护更具精确性和可控性的动画。这些新功能在最新的平台上可用,为SwiftUI开发者提供了更强大的动画工具。

相关内容

热门资讯

总算了解!(澳门太阳城)其实一... 总算了解!(澳门太阳城)其实一直都是有挂!太坑了原来一直都是有挂(2022已更新)(哔哩哔哩);澳门...
每日必看教程(友友联盟)外挂辅... 每日必看教程(友友联盟)外挂辅助器助手(辅助挂)详细教程(2021已更新)(哔哩哔哩);是一款可以让...
1个小技巧!德扑之星作弊(辅助... 1个小技巧!德扑之星作弊(辅助挂)原来一直都是有挂(2025已更新)(哔哩哔哩);致您一封信;亲爱玩...
免费测试版!(龙腾内蒙麻将)其... 免费测试版!(龙腾内蒙麻将)其实是有挂的!太难了原来一直总是有挂(2024已更新)(哔哩哔哩);龙腾...
热点推荐!多乐辅助器ios免费... 热点推荐!多乐辅助器ios免费版,德扑计算软件,详细教程(2022已更新)(哔哩哔哩)是一款可以让一...
揭秘一下(豆豆楚风麻将)外挂透... 揭秘一下(豆豆楚风麻将)外挂透明挂辅助器助手(辅助挂)详细教程(2023已更新)(哔哩哔哩);豆豆楚...
查到实测!(宜宾三打一)其实总... 查到实测!(宜宾三打一)其实总是有挂!太离谱了原来是有挂的(2022已更新)(哔哩哔哩);超受欢迎的...
9分钟了解!微扑克软件(辅助挂... 9分钟了解!微扑克软件(辅助挂)原来真的是有挂(2023已更新)(哔哩哔哩);微扑克中的10万兆豆可...
玩家必备攻略(涡阳茶馆)外挂透... 相信很多朋友都在电脑上玩过涡阳茶馆吧,但是很多朋友都在抱怨用电脑玩起来不方便。为此小编给大家带来了涡...
玩家亲测!浙江游戏大厅辅助,微... 玩家亲测!浙江游戏大厅辅助,微扑克wpk有挂,详细教程(2021已更新)(哔哩哔哩);亲,有的,ai...