Я пытаюсь сделать анимацию динамика в SwiftUI такой же, как в Apple Control Center Speaker или Brightness HUD. Я использую 4 изображения из SFSymbols, предоставленных Apple:
- "speaker.sla sh .fill"
// speakerEmpty
- "speaker.1.fill"
// speaker1
- "speaker.2.fill"
// speaker2
- "speaker.3.fill"
// speaker3
Итак, у меня есть переключатель (Включить 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")
}
}
}
Выбор динамика Наблюдаемый объект
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
}
}
}
}
Просмотр профиля
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)))
}
}
}
Полагаю, мой код logi c в порядке. Изображения заменяют нормально как надо. Но анимационный эффект не работает. Это расстраивает, я пробовал кучу возможных способов, но ни один не работает.