首页 > 其他分享 >在 SwiftUI 中的作用域动画

在 SwiftUI 中的作用域动画

时间:2024-07-12 20:28:21浏览次数:17  
标签:动画 作用域 修饰符 视图 secondStep SwiftUI var

在这里插入图片描述

在这里插入图片描述

文章目录

前言

从一开始,动画就是 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开发者提供了更强大的动画工具。

标签:动画,作用域,修饰符,视图,secondStep,SwiftUI,var
From: https://blog.csdn.net/qq_36478920/article/details/140387995

相关文章

  • Qt/QML学习-动画元素
    QML学习动画元素例程视频讲解代码main.qmlimportQtQuick2.15importQtQuick.Window2.15Window{width:640height:480visible:truetitle:qsTr("HelloWorld")Rectangle{id:rectwidth:50height:50......
  • swiftUI
    SwiftUI是苹果推出的一种现代化方式,用于创建跨所有Apple平台的用户界面。它通过声明性语法简化了UI的开发流程。下面是一个基本的SwiftUI示例,展示了如何使用SwiftUI构建一个简单的"HelloWorld"应用。示例步骤1.创建一个新的SwiftUI项目打开Xcode,选择"新建项目......
  • 前端 纯CSS border-radius画一个波浪动画
    利用border-radius生成椭圆并不是利用旋转的椭圆本身生成波浪效果,而是利用它去切割背景,产生波浪的效果。HTML:<h2>波浪动画</h2>SCSS:body{position:relative;align-items:center;min-height:100vh;background-color:rgb(118,218,255);ov......
  • 使用滤镜实现文字根据动画图片的效果
    上周写了一篇文字智能适配背景的文章,其中涉及到了色彩与滤镜方面的知识,也提到了直接在 CSS 上使用滤镜。今天,我们趁热打铁,使用 CSS 的滤镜写相对来说比较炸裂的文字根据动画图片的特效吧!一、动画与文字直接在 body 中放入一个 div 元素,然后用我男朋友高中时候原创......
  • Perl词法作用域:自定义编程环境的构建术
    ......
  • 【最新鸿蒙应用开发】——实现鸿蒙的动画效果
    鸿蒙动画效果UI(用户界面)中包含开发者与设备进行交互时所看到的各种组件(如时间、壁纸等)。属性作为接口,用于控制组件的行为。例如,开发者可通过位置属性调整组件在屏幕上的位置。属性值的变化,通常会引起UI的变化。动画可在UI发生改变时,添加流畅的过渡效果。如果不加入动画,属性将......
  • 扫描光效动画css实现
            想实现扫描生效的动画,主要是通过伪元素(::after)的定义,通常用于在元素后面添加装饰性的内容。在这个例子中,伪元素创建了一个动画效果,让它看起来像是一个扫描光效果。    主要css如下:.element{position:relative;/*使伪元素绝对定位相对于这......
  • 面壁智能发布端侧 AI 应用开发平台;快手推出肖像动画技术 LivePortrait丨 RTE 开发者日
      开发者朋友们大家好: 这里是「RTE开发者日报」,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享RTE(Real-TimeEngagement)领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、「有看点的会议」,但内容仅代表编辑的个人观点,......
  • SpringBoot彩蛋之定制启动画面
    写在前面在日常开发中,我们经常会看到各种各样的启动画面。例如以下几种①spring项目启动画面②mybatisplus启动画面③若依项目启动画面还有很多各式各样好看的启动画面,那么怎么定制这些启动画面呢?一、小试牛刀①新建一个SpringBoot项目②在项目的resources目录下新......
  • 前端面试题30(闭包和作用域链的关系)
    闭包和作用域链在JavaScript中是紧密相关的两个概念,理解它们之间的关系对于深入掌握JavaScript的执行机制至关重要。作用域链作用域链是一个链接列表,它包含了当前执行上下文的所有父级执行上下文的变量对象。每当函数被调用时,JavaScript引擎会创建一个新的执行上下文,其中......