0

SwiftUIプログラミングの非常に早い段階で、基本的にコンテナビュー内にカードのリストを表示しようとしています.一番上のカードが表示されています...各カードにはテキストビューがあり、タップするとカードビューがスタック/コンテナから削除されますビューとすぐ次のビューが表示されます。現在のアニメーションを削除して次のアニメーションを表示するときにトランジション アニメーションを追加したかったのですが、これまでのところうまくいきませんでした..驚くべきことに、Bool 変数を使用して表示/非表示に使用すると、トランジションは期待どおりに機能します。トップカードビューのみですが、取り外しと挿入を同時に実行したい場合はそうではありません..

import SwiftUI
import Combine

public struct CardsStackView: View {
   @ObservedObject
   public var viewModel: CardsStackViewModel

   public init(cards: [Card]) {
      self.viewModel = CardsStackViewModel(cards: cards)
   }

   public var body: some View {
      ZStack {
        Rectangle()
            .foregroundColor(.white)
            .zIndex(1)
        
        // idea is to remove the top card with slide transition and show next top one with scale transition alongside changing opacity.. wanting to do these both in sync
        cardView(for: viewModel.cards[viewModel.top])
            .zIndex(2)
            .transition(.asymmetric(insertion: .scale.combined(with: .opacity), removal: .slide.combined(with: .opacity)))
       }
    }

    private func cardView(for card: Card) -> some View {
      let view = CardView(card: card)

      viewModel.subscription = view.publisher
        .receive(on: DispatchQueue.main)
        .sink { event in
            if case .dismissed = event {
                // Animating, while changing the top published value in view model inside navigateToNext method
                withAnimation {
                    viewModel.navigateToNext()
                }
            }
      }

      return view
    }
}

Binding 変数を持つビュー モデルは次のとおりです。

import SwiftUI
import Combine

public class CardsStackViewModel: ObservableObject {
   public let cards: [Card]
   var subscription: AnyCancellable?

   @Published
   var top: Int = 0

   public init(cards: [Card]) {
      self.cards = cards
   }
    
   func navigateToNext() {
       guard top < cards.count - 1 else {
          return
       }
    
       top += 1
   }
 }

カードビューはこちら

import SwiftUI
import Combine

public enum CardViewEvent {
   case dismissed
}

public struct CardView: View {
   public let card: Card
   public let publisher = PassthroughSubject<CardViewEvent, Never>()

   public init(card: Card) {
      self.card = card
   }

   public var body: some View {
       ZStack(alignment: .leading) {
           Text(card.title)
            .onTapGesture {
               self.publisher.send(.dismissed)
            }
       }
   }
}

カードモデルは次のとおりです。

import SwiftUI

public struct Card: Identifiable {
   public let id = UUID().uuidString
   public let title: String

   public init(title: String) {
      self.title = title
   }
}

誰かがそれの何が問題なのかを指摘できる場合は感謝します。それとも、これは理想的なアプローチではありませんか?

4

1 に答える 1