You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xcode SwiftUI中Lottie动画缩放适配失效无法调整大小问题求助

问题原因
  • 核心问题是你的LottieView中封装的UIKit AnimationView没有配置自适应父容器尺寸的规则,默认UIKit视图会忽略SwiftUI设置的frame限制,优先按照自身内容尺寸撑开父容器
  • 额外问题:你设置了loopMode = .loop循环播放,动画永远不会走到结束状态,play方法的完成回调永远不会触发,animationInProgress赋值为false的逻辑永远不会执行,动画一旦启动就不会消失
  • 返回值使用some AnimationView的不透明类型会增加约束适配的异常概率,明确指定返回类型更稳妥
解决思路

第一步:修改LottieView封装逻辑

配置AnimationView的自适应规则,同时增加可复用参数方便后续自定义动画内容、播放模式:

import SwiftUI
import Lottie

struct LottieView: UIViewRepresentable {
    // 新增可配置参数,方便后续复用
    let animationName: String
    let loopMode: LottieLoopMode
    @Binding var animationInProgress: Bool
    
    func makeUIView(context: Context) -> AnimationView {
        let lottieAnimationView = AnimationView(name: animationName)
        // 核心修复:配置自适应父容器尺寸的规则
        lottieAnimationView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        lottieAnimationView.contentMode = .scaleAspectFit
        lottieAnimationView.loopMode = loopMode
        
        if animationInProgress {
            lottieAnimationView.play { complete in
                // 只有非循环模式下才需要这个回调逻辑
                if complete, loopMode != .loop {
                    animationInProgress = false
                }
            }
        }
        return lottieAnimationView
    }
    
    func updateUIView(_ uiView: AnimationView, context: Context) {
        // 响应状态变化控制播放/暂停
        if animationInProgress {
            uiView.play()
        } else {
            uiView.stop()
        }
    }
}

第二步:修改ContentView调用逻辑

调整参数传递,按需设置动画尺寸,要指定位置可以通过offset、position modifiers或者嵌套在Stack/ZStack的对应位置实现:

import SwiftUI

struct ContentView: View {
    @State var animationInProgress = false

    var body: some View {
        VStack{
            Text("My fruit Shop").font(.title).bold()
            Image("Fruit")
                .resizable()
                .cornerRadius(8)
                .frame(width: 300, height: 200)
            
            if animationInProgress {
                // 这里的frame设置会生效,不会再撑满屏幕
                LottieView(
                    animationName: "31626-e-mail",
                    loopMode: .loop,
                    animationInProgress: $animationInProgress
                )
                .frame(width: 60, height: 60)
                // 如果要调整位置,比如偏移到右上角可以加:
                // .offset(x: 100, y: -20)
            }
            
            Spacer()
            Button("Like this product", action: {
                animationInProgress.toggle()
            })
                .foregroundColor(.white)
                .padding()
                .background(Color.accentColor)
                .cornerRadius(8)
                .padding(.top, 50)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
后续功能实现建议

要实现点击按钮在指定位置展示指定尺寸的Lottie动画,只需要:

  • 新增@State变量存储动画需要展示的位置坐标
  • 点击按钮时同时更新animationInProgress和位置变量
  • 给LottieView添加position(x: positionX, y: positionY) modifier绑定位置变量即可

内容的提问来源于stack exchange,提问作者Maxime Sauvaget

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 18:06:05