SwiftUI 动画新技能,让你的应用「活」起来!

这里每天分享一个 iOS 的新知识,快来关注我吧

前言

在 SwiftUI 中,symbolEffect() 修饰符为 SF Symbols 提供了内置的动画效果,使得在应用中添加好看的动画变得非常容易。通过这些新特性,我们可以实现令人愉悦的用户体验,而且只需极少的代码量。

让我们来看看如何使用这些动画效果,以及如何在应用中实现一些有趣的动画。

基本动画效果

例如,我们可以为一个狗狗图标添加轻柔的上下弹跳效果,每当用户点击按钮时,图标就会做出响应:

css 复制代码
struct ContentView: View {
    @State private var petCount = 0
    var body: some View {
        Button {
            petCount += 1
        } label: {
            Label("Pet the Dog", systemImage: "dog")
        }
        .symbolEffect(.bounce, value: petCount)
        .font(.largeTitle)
    }
}

效果:

多层动画

除了基本动画,我们还可以利用 SF Symbols 的多层特性实现更复杂的效果。默认情况下,多个图层会单独进行动画处理,比如 "mail.stack" 这样的图标可以产生波浪般的效果:

css 复制代码
struct ContentView: View {
    @State private var isFavorite = false
    var body: some View {
        Button {
            isFavorite.toggle()
        } label: {
            Label("Activate Inbox Zero", systemImage: "mail.stack")
        }
        .symbolEffect(.bounce.down, value: isFavorite)
        .font(.largeTitle)
    }
}

效果:

高级动画效果

对于能够支持 iOS 18 或更高版本的应用,我们可以使用.rotate动画来让图标旋转。这在带有箭头等元素的图标上效果特别好。比如,让刷新箭头在点击时旋转:

css 复制代码
struct ContentView: View {
    @State private var animate = false
    var body: some View {
        Button {
            animate.toggle()
        } label: {
            Image(systemName: "arrow.clockwise.square")
                .symbolEffect(.rotate, value: animate)
                .font(.largeTitle)
        }
    }
}

自定义动画速度和次数

SwiftUI 提供了多种动画变体,你甚至可以通过额外选项自定义动画速度和重复次数。例如,下列代码以 3 倍速重复 3 次地动画符号:

css 复制代码
struct ContentView: View {
    @State private var isFavorite = false
    var body: some View {
        Button {
            isFavorite.toggle()
        } label: {
            Label("Activate Inbox Zero", systemImage: "mail.stack")
        }
        .symbolEffect(.bounce, options: .speed(3).repeat(3), value: isFavorite)
        .font(.largeTitle)
    }
}

效果:

变量颜色动画

变量颜色动画特别强大,因为 SF Symbols 可以控制每层动画的显示方式。.variableColor.iterative 会逐层着色,而 .variableColor.cumulative 会累计地添加颜色。此外,你可以为这些动画添加reversing,使动画向前播放后再倒退。

less 复制代码
struct ContentView: View {
    @Stateprivatevar animationsRunning = false
    var body: some View {
        Button("Start Animations") {
            withAnimation {
                animationsRunning.toggle()
            }
        }
        VStack {
            HStack {
                Image(systemName: "square.stack.3d.up")
                    .symbolEffect(.variableColor.iterative, value: animationsRunning)
                Image(systemName: "square.stack.3d.up")
                    .symbolEffect(.variableColor.cumulative, value: animationsRunning)
                Image(systemName: "square.stack.3d.up")
                    .symbolEffect(.variableColor.reversing.iterative, value: animationsRunning)
                Image(systemName: "square.stack.3d.up")
                    .symbolEffect(.variableColor.reversing.cumulative, value: animationsRunning)
            }
            HStack {
                Image(systemName: "square.stack.3d.up")
                    .symbolEffect(.variableColor.iterative, options: .repeating, value: animationsRunning)
                Image(systemName: "square.stack.3d.up")
                    .symbolEffect(.variableColor.cumulative, options: .repeat(3), value: animationsRunning)
                Image(systemName: "square.stack.3d.up")
                    .symbolEffect(.variableColor.reversing.iterative, options: .speed(3), value: animationsRunning)
                Image(systemName: "square.stack.3d.up")
                    .symbolEffect(.variableColor.reversing.cumulative, options: .repeat(3).speed(3), value: animationsRunning)
            }
        }
        .font(.largeTitle)
    }
}

效果:

使用内容过渡

如果你只想对标签的内容进行更换,而保持视图不变,建议使用 contentTransition() 修饰符。例如,可以通过 .replace 过渡效果让一个图标淡出而另一个图标出现:

css 复制代码
struct ContentView: View {
    @Stateprivatevar isFavorite = false
    var body: some View {
        VStack {
            Button {
                withAnimation {
                    isFavorite.toggle()
                }
            } label: {
                Label("Toggle Favorite", systemImage: isFavorite ? "checkmark" : "heart")
            }
            .contentTransition(.symbolEffect(.replace))
        }
        .font(.largeTitle)
    }
}

效果:

通过以上例子,可以看到 SwiftUI 提供的 SF Symbols 动画是非常强大和灵活的。

无论是简单还是复杂的应用场景,你都能找到合适的动画来增强用户体验。特别是对于没有设计经验的独立开发者来说,这是一个非常好的选择。

这里每天分享一个 iOS 的新知识,快来关注我吧

本文同步自微信公众号 "iOS新知",每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!

相关推荐
黑化旺仔10 小时前
【OC】KVO
macos·ios·objective-c·cocoa
HouWan12 小时前
SwiftUI 小技巧:如何读取 SwiftUI Font 的详细信息
ios·swiftui·apple
李游Leo12 小时前
HarmonyOS 7 实战开发 05:把页面做到可上线状态
ios·harmonyos
终端安全笔记17 小时前
描述文件、企业证书、MDM 不是三个名字,是三层
android·ios·智能手机
传奇开心果编程18 小时前
【SwiftUI入门练中学】第1课 从零开始
学习·ui·ios·swiftui·swift
丿Wayne1 天前
iOS Token 刷新实战(Actor 避免并发重复刷新)
ios·swift·token·actor·swift并发
终端安全笔记2 天前
iOS 27 给了租赁一个新工具,但它只认受监督的设备
android·网络·安全·ios
大熊猫侯佩2 天前
独立 App 首发完成 iPhone Duo 展开态适配
ios·swiftui·swift
光影少年2 天前
setImmediate 和 setTimeout(0) 的区别
android·前端·react.js·ios·前端框架