我有一个传统的UIImageView,它使用CABasicAnimation来制作动画.我将其包装在UIViewRepresentable中,以便将其嵌入到SwiftUI视图中.它非常适用于主视图,但在使用.sheet修改器呈现的视图中,它不会产生动画效果.我的全部代码如下(用Xcode15.3编译).

import SwiftUI

@main
struct MyApp: App {
  var body: some Scene {
    WindowGroup {
      ContentView()
    }
  }
}

struct Microphone: UIViewRepresentable {
  func updateUIView(_ uiView: UIImageView, context: Context) {
  }
  
  func makeUIView(context: Context) -> UIImageView {
    let view = UIImageView(
      image:
        UIImage(
          systemName: "mic.circle.fill",
          withConfiguration: UIImage.SymbolConfiguration(pointSize: 50,weight: .bold, scale: .large)
        )?
        .withRenderingMode(.alwaysTemplate)
    )
    view.translatesAutoresizingMaskIntoConstraints = false
    view.tintColor = .green

    let animation = CABasicAnimation(keyPath: "transform.scale")
    animation.duration = 1.3
    animation.repeatCount = .greatestFiniteMagnitude
    animation.autoreverses = true
    animation.fromValue = 0.9
    animation.toValue = 1.1

    view.layer.add(animation, forKey: "scale")
    return view
  }
}

struct ContentView: View {
  @State var showSheet = false

  var body: some View {
    VStack {
      Microphone() // <-- animates perfectly
        .frame(width: 50, height: 50)

      Button("Show Sheet") { showSheet = true }
        .padding(.top)
    }
    .sheet(isPresented: $showSheet) {
      VStack {
        Microphone() // <-- does not animate
          .frame(width: 50, height: 50)
      }
    }
  }
}

#Preview {
    ContentView()
}

我 Select UIViewRepresentable美元的原因是

  1. 该代码已经编写、测试和接受.
  2. 我无法制作一个原生的SwiftUI视图来流畅地制作动画,这可能是因为我的SwiftUI知识仍然相当初级.我很乐意 Select 一个解决方案,让我在纯SwiftUI中获得流畅的动画效果.

推荐答案

判断内存图调试器,为工作表中的图像视图创建的CABasicAnimation由于某种原因被释放.从我的实验中,我还发现,如果在一段延迟后调用layer.add(animation),动画确实会被添加.我认为这要么是SwiftUI错误,要么是视图不知何故还没有为添加动画做好准备.

layoutSubviews部作品中添加动画,至少:

class ImageViewSubclass: UIImageView {
    override func layoutSubviews() {
        super.layoutSubviews()
        // optionally, check layer.animation(forKey: "scale") == nil first
        let animation = CABasicAnimation(keyPath: "transform.scale")
        animation.duration = 1.3
        animation.repeatCount = .greatestFiniteMagnitude
        animation.autoreverses = true
        animation.fromValue = 0.9
        animation.toValue = 1.1
        layer.add(animation, forKey: "scale")
    }
}

// in makeUIView:

let view = ImageViewSubclass(...)
...
return view

可能还有其他生命周期方法可以做到这一点.


制作此类动画的纯SwiftUI方法是:

struct Microphone: View {
    @State private var scale = 0.9
    
    var body: some View {
        Image(systemName: "mic.circle.fill")
            .imageScale(.large)
            .font(.system(size: 50, weight: .bold))
            .foregroundStyle(.green)
            .scaleEffect(scale)
            .onAppear {
                withAnimation(.linear(duration: 1.3).repeatForever(autoreverses: true)) {
                    scale = 1.1
                }
            }
            
    }
}

Ios相关问答推荐

Flutter中抛出后期应用错误

UIImage大小调整工作,但转换为上传数据时恢复到原始大小

如何使视图完全适合屏幕,而不会在旋转时溢出手机屏幕的边界?

与iPadOS中带有扣件的模式相似的组件是什么?

IFrame内容拒绝仅在iOS浏览器上加载-即使发布了内容-安全-策略(CSP)框架-祖先指令

如何在集合视图中创建装饰视图?

为什么 Firebase Messaging 配置对于 IOS native 和 Flutter iOS 不同?

不可发送类型 '[String : Any]?'在调用非隔离实例方法 XXX 时退出主参与者隔离上下文不能跨越参与者边界

部分保留 UITextField 中的占位符

当 Swift 枚举具有 any existential 作为其关联值之一时,我如何使它符合 `Equatable`?

RealityKit – ARView 光线投射返回 0 个结果

我需要二进制文件来进行 App Store 应用程序传输吗?

滚动 swiftUI 列表时,未调用单元格的任务修饰符.怎么修?

视图之间的 SwiftUI 过渡,没有过渡

SwiftUI - 使用切换switch 切换键盘类型(默认/数字)?

搜索在 ios xamarin.forms 中不起作用

SensorKit - 获取数据不调用结果委托函数

Swift - 获取设备的 WIFI IP 地址

UITextView 内容插图

iPhone UITableView.如何开启音乐 App 之类的单字母字母列表?