danielsaidi / DeckKit

DeckKit is a Swift SDK that helps you build deck-based apps in SwiftUI.
MIT License
653 stars 14 forks source link

Flipping a deck item flips the whole stack #5

Closed appfrosch closed 1 year ago

appfrosch commented 1 year ago

I'd llike to flip the frontmost deck item to show its backside–but instead the whole stack flips. Is there something I am missing?

Here's my code:

import SwiftUI

struct ContentView: View {
    var body: some View {
        CardStackView()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

struct Card: DeckItem {
    let id = UUID()
    let frontLabel: String
    let backLabel: String
    let color: Color
}

import DeckKit
struct CardStackView: View {
    @State private var deck = Deck(items: [
        Card(frontLabel: "front1", backLabel: "back1", color: .red),
        Card(frontLabel: "front2", backLabel: "back2", color: .green),
        Card(frontLabel: "front3", backLabel: "back3", color: .blue),
        Card(frontLabel: "front4", backLabel: "back4", color: .red),
    ])
    @State private var flipped = false

    var body: some View {
        DeckView(deck: $deck) { deckItem in
            ZStack {
                RoundedRectangle(cornerRadius: 10.0)
                    .foregroundColor(deckItem.color)
                    .frame(width: 300.0, height: 300.0)
                Text(flipped ? deckItem.backLabel : deckItem.frontLabel)
                    .rotation3DEffect(Angle(degrees: flipped ? 0 : 180), axis: (x: 0.0, y: 1.0, z: 0.0)) //show front side unmirrored
            }
            .rotation3DEffect(Angle(degrees: flipped ? 0 : 180), axis: (x: 0.0, y: 1.0, z: 0.0))
            .onTapGesture {
                withAnimation(.linear(duration: 2.0)) {
                    flipped.toggle() // expectation: the frontmost card flips, what happens though is that the whole stack flips
                }
            }
        }
    }
}

Also, here's a little video showing what's happening:

https://user-images.githubusercontent.com/91844195/217499165-7761e858-eba8-45b2-8b36-8f9867063908.mov

appfrosch commented 1 year ago

I guess one approach would be to introduce another RoundedRect that fades in and flips, thus covering the original stack. Is this a valid approach do you think or is there any other way that I am not seeing?

danielsaidi commented 1 year ago

Hi @appfrosch

First of all, thank you so much for sponsoring! 🙏

Can't you add a state property to the card view and use it to trigger a flip within the card view instead of flipping the deck?

appfrosch commented 1 year ago

Yep, if I introduce the flip state into the Card model, I can work with that–thanks. Not entirely there yet (the animation is not exactly what I am looking for yet) but I can see how it must go. I think I will make a small blogpost on this any time this week, thanks for pushing me into the right direction 🤗 Will leave this open to refer to the blogpost once I managed to create it.

danielsaidi commented 1 year ago

Oh cool, just let me know when it's up and I'd be happy to share it! :)

I could also add flipping to the demo app if you think it could help others. I just don't have the time to do so right now.

appfrosch commented 1 year ago

Here's the link to my tutorial on this.

danielsaidi commented 1 year ago

Wow, such a great read @appfrosch 🤩

Just a thought - wouldn't it be easier to create a separate card view and contain the flipped state within the view instead of adding it to the model? Also, if you think about it - the flipped state should probably be scoped to the view and not the model itself. I mean, what if you present the same item in two different stacks?

Just a thought :)