While creating animation logic so that when the button is pressed, the Card would swipe away, however, with the current approach by using State and Binding nothing happens.
I suppose the trick here is that I'm not letting the card view know when the button is triggered.
Here's button where @State private var isFLipped = false
:
Button(action: {
// Handle button action
// isTapped.toggle()
isFLipped.toggle()
}) {
Text("👍")
.frame(width: 70, height: 50)
.background(Color("Easy"))
.clipShape(RoundedRectangle(cornerRadius: 8))
}
Here's SingleCardView:
ZStack {
RoundedRectangle(cornerRadius: 25, style: .continuous)
.fill(Color.white)
.overlay(RoundedRectangle(cornerRadius: 25).stroke(getColor(), lineWidth: 2))// Here we change the border color based on the swipe direction
.shadow(radius: 3)
VStack {
NavigationStack {
Text(card.term ?? "Unnamed Card")
Divider()
if isTapped {
Text(card.definition ?? "Unnamed Card")
}
}
}
}
.frame(width: 300, height: 500)
.rotation3DEffect(
Angle(degrees: isFLipped ? 360: 0),
axis: (x: 0, y: isFLipped ? 360 : 0, z: 0)
)
.onTapGesture {
isTapped.toggle()
}
}
The SwiftUI way/most efficient of doing this would be to have a value type in an @State
and sharing isFlipped
as an @Binding
import SwiftUI
struct SampleSharedManagerView: View {
@State private var isFlipped: Bool = false
var body: some View {
NavigationStack{
List {
Section("first") {
FirstView(isFlipped: $isFlipped)
}
Section("second") {
SecondView(isFlipped: $isFlipped)
}
}
}
}
}
struct FirstView: View {
@Binding var isFlipped: Bool
var body: some View {
Image(systemName: "person")
.rotation3DEffect(Angle(degrees: isFlipped ? 360: 0), axis: (x: 0, y: isFlipped ? 360 : 0, z: 0))
.animation(.easeInOut(duration: 2), value: isFlipped)
}
}
struct SecondView: View {
@Binding var isFlipped: Bool
var body: some View {
Button("Toggle") {
isFlipped.toggle()
}.buttonStyle(.borderedProminent)
}
}
But if we assume that the 2 Views are separated by various layers we can tap into Combine
and have a shared source of truth.
import SwiftUI
import Combine
class AppEventsManager {
static let shared = AppEventsManager()
var isFlipped : CurrentValueSubject<Bool, Never> = .init(true)
private init() { }
}
Then you can subscribe to changes in the Views that need them.
//Observes changes
struct FirstView: View {
@State private var isFlipped: Bool = false
@State private var cancellables: Set<AnyCancellable> = []
var body: some View {
Image(systemName: "person")
.rotation3DEffect(Angle(degrees: isFlipped ? 360: 0), axis: (x: 0, y: isFlipped ? 360 : 0, z: 0))
.animation(.easeInOut(duration: 2), value: isFlipped)
.task {
AppEventsManager.shared.isFlipped
.receive(on: DispatchQueue.main)
.sink { isFlipped in
self.isFlipped = isFlipped
}
.store(in: &cancellables)
}.onDisappear {
self.cancellables = .init()
}
}
}
//Makes Changes
struct SecondView: View {
let manager = AppEventsManager.shared
var body: some View {
Button("Toggle") {
manager.isFlipped.send(!manager.isFlipped.value)
}.buttonStyle(.borderedProminent)
}
}