我试图制作一个SWIFTUI View,该SWIFTUI View可以通过使用gesture()方法来进行类似卡片刷卡的动作。但是我想不出一种方法来使视图一个一个地滑动。目前,当我滑动所有视图时,
import SwiftUI
struct EventView: View {
@State private var offset: CGSize = .zero
@ObservedObject var randomView: EventViewModel
var body: some View {
ZStack{
ForEach(randomView.randomViews,id:\.id){ view in
view
.background(Color.randomColor)
.cornerRadius(8)
.shadow(radius: 10)
.padding()
.offset(x: self.offset.width, y: self.offset.height)
.gesture(
DragGesture()
.onChanged { self.offset = $0.translation }
.onEnded {
if $0.translation.width < -100 {
self.offset = .init(width: -1000, height: 0)
} else if $0.translation.width > 100 {
self.offset = .init(width: 1000, height: 0)
} else {
self.offset = .zero
}
}
)
.animation(.spring())
}
}
}
}
struct EventView_Previews: PreviewProvider {
static var previews: some View {
EventView(randomView: EventViewModel())
}
}
struct PersonView: View {
var id:Int = Int.random(in: 1...1000)
var body: some View {
VStack(alignment: .center) {
Image("testBtn")
.clipShape(/*@START_MENU_TOKEN@*/Circle()/*@END_MENU_TOKEN@*/)
Text("Majid Jabrayilov")
.font(.title)
.accentColor(.white)
Text("iOS Developer")
.font(.body)
.accentColor(.white)
}.padding()
}
}
使用这段代码,当我轻扫整个内容时
答案 0 :(得分:1)
基本上,您的代码告诉每个视图都遵循偏移量,而实际上您只希望前一个动作。因此,首先我要添加一个变量,该变量将保存卡的当前索引,并提供一种计算其偏移量的方法:
@State private var currentCard = 0
func offset(for i: Int) -> CGSize {
return i == currentCard ? offset : .zero
}
第二,我发现,如果我们只是这样保留它,则在下一个触摸视图上将获得上一个(-1000,0)的偏移量,然后才跳转到正确的位置,因此它看起来就像上一个卡决定返回,而不是新的卡。为了解决这个问题,我添加了一个标记来标记该卡已用完,因此当我们再次触摸它时,它最初会定位在正确的位置。通常,我们会在手势的.began
状态下执行此操作,但是在swiftUI中没有类似的操作,因此唯一的执行位置是在.onChanged
中:
@State private var didJustSwipe = false
DragGesture()
.onChanged {
if self.didJustSwipe {
self.didJustSwipe = false
self.currentCard += 1
self.offset = .zero
} else {
self.offset = $0.translation
}
}
如果成功,我们在.onEnded
中分配didJustSwipe = true
因此,现在它可以完美运行了。另外,我建议您将代码分成更小的部分。它不仅可以提高可读性,而且可以节省一些编译时间。您没有提供EventViewModel
和那些randomViews
的实现,所以我改用了矩形。这是您的代码:
struct EventView: View {
@State private var offset: CGSize = .zero
@State private var currentCard = 0
@State private var didJustSwipe = false
var randomView: some View {
return Rectangle()
.foregroundColor(.green)
.cornerRadius(20)
.frame(width: 300, height: 400)
.shadow(radius: 10)
.padding()
.opacity(0.3)
}
func offset(for i: Int) -> CGSize {
return i == currentCard ? offset : .zero
}
var body: some View {
ZStack{
ForEach(currentCard..<5, id: \.self) { i in
self.randomView
.offset(self.offset(for: i))
.gesture(self.gesture)
.animation(.spring())
}
}
}
var gesture: some Gesture {
DragGesture()
.onChanged {
if self.didJustSwipe {
self.didJustSwipe = false
self.currentCard += 1
self.offset = .zero
} else {
self.offset = $0.translation
}
}
.onEnded {
let w = $0.translation.width
if abs(w) > 100 {
self.didJustSwipe = true
let x = w > 0 ? 1000 : -1000
self.offset = .init(width: x, height: 0)
} else {
self.offset = .zero
}
}
}
}