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