我有一个 SwiftUI 应用程序,其行为类似于 Tinder(使用本指南构建- 或查看源代码)。您只需左右滑动一堆卡片。我有一个“竖起大拇指”和“竖起大拇指”按钮作为刷卡的替代品,但是当它们被按下时,我希望它为用户刷卡,就好像他们自己刷卡一样。
在没有 UIKit 的 SwiftUI 中有什么方法可以做到这一点?
If your thumbs up and down buttons were part of the CardView
then it would be quite simple to achieve: just repeat whatever code executes on gesture inside a button action. Something along these lines:
// CardView.swift
Button (action: {
// hardcoded for simplicity
self.translation = .init(width: 100, height: 0)
self.swipeStatus = .like
// a hacky way to "wait" for animation to complete
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3, execute: {
self.onRemove(self.user)
})
}) {
Image(systemName: "hand.thumbsup")
.foregroundColor(.green)
}
But, if your buttons reside outside of the CardView
, I think you'll have to re-architect your views a little bit. I would start by converting swipeStatus
from @State
into a @Binding
, so its value can be passed down from the parent view. Then you will need to declare a state variable in your ContentView
, which you can then tie together with swipeStatus
binding. Something like:
// ContentView.swift
@State var currentSwipeStatus: LikeDislike = .none
....
CardView(
swipeStatus: self.users.last == user
? $currentSwipeStatus
: .constant(.none),
user: user,
onRemove: { removedUser in
self.users.removeAll { $0.id == removedUser.id}
self.swipeStatus = .none
})
Within your card view you'll need to react to the bound value changing. I just appended onChange
to the main VStack
:
.onChange(of: swipeStatus) { newState in
if newState == .like {
self.translation = .init(width: 100, height: 0)
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3, execute: {
self.onRemove(self.user)
})
}
}
I feel like there's a more elegant way of achieving this. I'm not a big fan of the onRemove
callback, asyncAfter
hack, and the fact that they render all cards at once.
But at least that's a start.