Xcode集成lottie动画
Xcode集成lottie动画

Xcode集成lottie动画

前情提要

因为要改版我的“存钱猪猪”应用,在应用的启动环境,想要提供一个加载动画,防止让用户存在视觉的卡顿效果。

因此在Gif动画和lottie动画中,选择使用lottie动画作为后续应用动画的首选。

操作流程

配置Xcode

在Xcode中打开对应的项目文件,点击左侧顶部的项目名称,选择选项卡中的PROJECT -> Package Dependencies -> Packages,点击左下角的添加按钮。

在弹出框中输入下面的Git仓库名称,然后点击“Add Package”按钮。

https://github.com/airbnb/lottie-ios

等待片刻,安装完成。然后在Add to Target中选择我们的项目,再点击“Add Package”按钮,将lottie添加到我们的项目中。

配置文件

首先,我们将lottie的json文件导入到我们的项目中,我在这里先创建了一个animation.scnassets文件夹来管理lottie动画文件,右击选择“Add Files to 项目名”。

选中对应的lottie动画的json文件,导入到Xcode中。

导入后的效果图:

创建一个LottieView视图文件,具体代码如下:

import SwiftUI
import Lottie

struct LottieView: UIViewRepresentable {
    var filename: String
    
    func makeUIView(context: Context) -> UIView {
        let view = UIView(frame: .zero)
        
        // 创建 Lottie 动画视图
        let animationView = LottieAnimationView(name: filename) // 使用 LottieAnimationView 而不是 AnimationView
        animationView.contentMode = .scaleAspectFit
        animationView.loopMode = .loop
        animationView.play()
        
        animationView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(animationView)
        
        NSLayoutConstraint.activate([
            animationView.widthAnchor.constraint(equalTo: view.widthAnchor),
            animationView.heightAnchor.constraint(equalTo: view.heightAnchor)
        ])
        
        return view
    }
    
    func updateUIView(_ uiView: UIView, context: Context) {}
}

最后,我们在视图中使用:

LottieView(filename: "loading") // 替换为你的 Lottie 文件名

代码进行lottie动画的展示。

完成效果:

资源

LottieFiles: https://lottiefiles.com/

扩展知识

如果想要控制lottie动画的播放和循环次数,可以使用下面的代码:

import SwiftUI
import Lottie

struct LottieView: UIViewRepresentable {
    var filename: String
    var isPlaying: Bool // 控制是否播放
    var playCount: Int // 播放次数,0 表示无限循环
    var isReversed: Bool // 是否倒放

    class Coordinator {
        var parent: LottieView
        init(parent: LottieView) {
            self.parent = parent
        }
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(parent: self)
    }

    func makeUIView(context: Context) -> UIView {
        let view = UIView(frame: .zero)
        
        // 创建 Lottie 动画视图
        let animationView = LottieAnimationView(name: filename)
        animationView.contentMode = .scaleAspectFit
        animationView.translatesAutoresizingMaskIntoConstraints = false
        animationView.loopMode = playCount == 0 ? .loop : .playOnce
        view.addSubview(animationView)
        
        NSLayoutConstraint.activate([
            animationView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            animationView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            animationView.topAnchor.constraint(equalTo: view.topAnchor),
            animationView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        ])
        
        if isPlaying {
            playAnimation(animationView, playCount: playCount, isReversed: isReversed)
        }
        
        return view
    }

    func updateUIView(_ uiView: UIView, context: Context) {
        guard let animationView = uiView.subviews.first as? LottieAnimationView else { return }
        
        if isPlaying {
            playAnimation(animationView, playCount: playCount, isReversed: isReversed)
        } else {
            animationView.stop()
        }
    }

    // 播放动画的辅助方法
    private func playAnimation(_ animationView: LottieAnimationView, playCount: Int, isReversed: Bool) {
        animationView.animationSpeed = isReversed ? -1 : 1

        if isReversed {
            animationView.currentProgress = 1 // 从最后一帧开始倒放
        }

        if playCount == 0 {
            animationView.loopMode = .loop
            animationView.play()
        } else {
            animationView.loopMode = .playOnce
            animationView.play { _ in
                if playCount > 1 {
                    playAnimation(animationView, playCount: playCount - 1, isReversed: isReversed)
                }
            }
        }
    }
}

SwiftUI中使用按钮控制播放效果:

struct ContentView: View {
    @State private var isPlaying = false
    @State private var isReversed = false

    var body: some View {
        VStack {
            LottieView(filename: "success", isPlaying: isPlaying, playCount: 2, isReversed: isReversed)
                .frame(width: 200, height: 200)

            HStack {
                Button(action: {
                    isReversed = false
                    isPlaying = true
                    DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
                        isPlaying = false
                    }
                }) {
                    Text("正向播放")
                        .padding()
                        .background(Color.green)
                        .foregroundColor(.white)
                        .cornerRadius(8)
                }

                Button(action: {
                    isReversed = true
                    isPlaying = true
                    DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
                        isPlaying = false
                    }
                }) {
                    Text("倒放")
                        .padding()
                        .background(Color.red)
                        .foregroundColor(.white)
                        .cornerRadius(8)
                }
            }
        }
    }
}

实现逻辑

1、默认暂停:通过 isPlaying 的状态控制是否播放。

2、播放指定次数:通过 playCount 传递目标次数。

3、延迟停止:在按钮触发时,通过 DispatchQueue 设置动画播放的时间上限。

4、倒放控制:通过 isReversed 参数设置动画速度为 -1。

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开放者。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注