在 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开发者提供了更强大的动画工具。

相关内容

热门资讯

透视存在!德普之星透视辅助软件... 透视存在!德普之星透视辅助软件激活码,德普之星辅助器app,细节揭秘(有挂解密);是一款可以让一直输...
透视安卓版!wepoker私人... 透视安卓版!wepoker私人局透视方法(透视)其实真的是有挂(软件教程)1、让任何用户在无需wep...
透视透视挂!aapoker发牌... 透视透视挂!aapoker发牌逻辑,aapoker怎么选牌,曝光教程(有挂规律)暗藏猫腻,小编详细说...
透视最新!德普之星私人局透视,... 透视最新!德普之星私人局透视,德普之星有辅助软件吗,攻略教程!(有挂工具)是一款可以让一直输的玩家,...
透视真的!wepoker作弊辅... 透视真的!wepoker作弊辅助(透视)真是存在有挂(攻略教程)1、玩家可以在wepoker作弊辅助...
透视有挂!aapoker公共底... 透视有挂!aapoker公共底牌,aapoker怎么开辅助器,必赢方法(有挂工具)暗藏猫腻,小编详细...
透视计算!wejoker开挂(... 透视计算!wejoker开挂(透视)都是是有挂(解密教程)1、每一步都需要思考,不同水平的挑战会更加...
透视苹果版!德普之星辅助器ap... 透视苹果版!德普之星辅助器app,德普之星私人局辅助免费,攻略方法(有挂攻略)1、许多玩家不知道德普...
透视教程!aapoker透视怎... 透视教程!aapoker透视怎么用,aapoker透视脚本入口,解密教程(有挂辅助)1、打开软件启动...
透视系统!we-poker辅助... 透视系统!we-poker辅助软件教程(透视)真是真的是有挂(解说技巧)1、进入到we-poker辅...