在 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
}
}
感谢是否有人可以指出它有什么问题。或者这不是理想的方法?