gpt4 book ai didi

SwiftUI:无法为图像设置动画

转载 作者:行者123 更新时间:2023-12-04 10:39:03 27 4
gpt4 key购买 nike

我正在尝试在 SwiftUI 中制作与 Apple 的控制中心扬声器或亮度 HUD 类似的扬声器动画。我正在使用 Apple 提供的 SFSymbols 中的 4 张图像:

  • "speaker.slash.fill"// speakerEmpty
  • "speaker.1.fill"// speaker1
  • "speaker.2.fill"// speaker2
  • "speaker.3.fill"// speaker3

  • 所以,我有一个 Switch(在 SwiftUI 中切换)来用四个图像的动画来切换我的声音选项。这就是我希望图像动画的方式:
    当开关打开时:
  • speakerEmpty应该动画到 -> speaker1然后
  • speaker1应该动画到 -> speaker2然后
  • speaker2应该动画到 -> speaker3

  • 并在切换关闭时反转。

    这是我试过的代码:

    SpeakerSymbol Enum


    import SwiftUI

    enum SpeakerSymbol:CaseIterable {
    case speakerEmpty, speaker1, speaker2, speaker3

    var image:Image {
    switch self {
    case .speakerEmpty: return Image(systemName: "speaker.slash.fill")
    case .speaker1: return Image(systemName: "speaker.1.fill")
    case .speaker2: return Image(systemName: "speaker.2.fill")
    case .speaker3: return Image(systemName: "speaker.3.fill")
    }
    }
    }

    Speaker Selection Observable Object


    final class SpeakerSelection: ObservableObject {
    @Published var selectedSymbol:SpeakerSymbol = .speaker3
    @Published var isSoundEnabled = true {
    didSet {
    if isSoundEnabled {
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
    self.selectedSymbol = .speakerEmpty
    }
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
    self.selectedSymbol = .speaker1
    }
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
    self.selectedSymbol = .speaker2
    }
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
    self.selectedSymbol = .speaker3
    }
    } else {
    selectedSymbol = .speaker3
    selectedSymbol = .speaker2
    selectedSymbol = .speaker1
    selectedSymbol = .speakerEmpty

    }
    }
    }
    }

    Profile View


    struct ProfileView: View {
    @ObservedObject var selection = SpeakerSelection()

    var body: some View {

    NavigationView {
    VStack {
    Spacer()
    Text("Speaker Toggle").font(.largeTitle)
    Spacer()

    Toggle(isOn: withAnimation {
    $selection.isSoundEnabled
    }, label: {
    selection.selectedSymbol.image
    .frame(width: 50)
    .animation(Animation.default.delay(0.2))
    .transition(.asymmetric(insertion: .opacity, removal: .opacity))
    // speakerSymbol()
    Text("Sound")
    }).padding().animation(.default).font(.largeTitle)
    Spacer()
    Spacer()
    }
    }
    }
    func speakerSymbol() -> AnyView {
    switch selection.selectedSymbol {
    case .speakerEmpty: return AnyView(SpeakerSymbol.speakerEmpty.image
    .animation(Animation.default.delay(0.2))
    .transition(.asymmetric(insertion: .opacity, removal: .opacity)))
    case .speaker1: return AnyView(SpeakerSymbol.speaker1.image
    .animation(Animation.default.delay(0.2))
    .transition(.asymmetric(insertion: .opacity, removal: .opacity)))
    case .speaker2: return AnyView(SpeakerSymbol.speaker2.image
    .animation(Animation.default.delay(0.2))
    .transition(.asymmetric(insertion: .opacity, removal: .opacity)))
    case .speaker3: return AnyView(SpeakerSymbol.speaker3.image
    .animation(Animation.default.delay(0.2))
    .transition(.asymmetric(insertion: .opacity, removal: .opacity)))
    }
    }
    }

    我想我的代码逻辑很好。图像正在按原样替换。但是没有动画效果工作。令人沮丧的是,我尝试了很多可能的方法,但都没有奏效。

    最佳答案

    这是可能的方法。我出于演示目的简化了它并减少了发布代码,但想法应该清晰且易于转移到您的真实代码

    结果演示(确实比在 gif 上流畅得多):

    enter image description here

    修改模型

    enum SpeakerSymbol: Int, CaseIterable { // Inherited from Int for convenient below

    case speakerEmpty, speaker1, speaker2, speaker3

    var image: some View {
    var name: String
    switch self {
    case .speakerEmpty: name = "speaker.slash.fill"
    case .speaker1: name = "speaker.1.fill"
    case .speaker2: name = "speaker.2.fill"
    case .speaker3: name = "speaker.3.fill"
    }
    return Image(systemName: name).font(.largeTitle)
    }
    }

    SpeakerSymbol 的可动画修饰符,需要让 SwiftUI 动画知道更改的 SpeakerSymbol 值能够动画
    struct SpeakerModifier: AnimatableModifier {
    var symbol: SpeakerSymbol

    init(symbol: SpeakerSymbol) {
    self.symbol = symbol
    self.animating = Double(symbol.rawValue) // enum to Double
    }

    private var animating: Double // Double supports Animatable
    var animatableData: Double { // required part of Animatable protocol
    get { animating }
    set { animating = newValue }
    }

    func body(content: Content) -> some View {
    return SpeakerSymbol(rawValue: Int(animating))!.image // Double -> enum
    }
    }

    使用演示
    struct TestSpeakerModifier: View {
    @State private var speaker: SpeakerSymbol = .speakerEmpty

    var body: some View {
    VStack {
    Color.clear // << just holder area
    .modifier(SpeakerModifier(symbol: speaker))
    .frame(width: 80, height: 80)
    Divider()
    Button("Toggle") {
    withAnimation { // animates between enum states
    self.speaker =
    (self.speaker == .speakerEmpty ? .speaker3 : .speakerEmpty)
    }
    }
    }
    }
    }

    关于SwiftUI:无法为图像设置动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60020224/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com