Cocoa touch 如何在SwiftUI中将拖动手势限制为仅一个方向?
我尴尬地花了两周的时间来解决这个问题 我想做的是:Cocoa touch 如何在SwiftUI中将拖动手势限制为仅一个方向?,cocoa-touch,swiftui,ios13,Cocoa Touch,Swiftui,Ios13,我尴尬地花了两周的时间来解决这个问题 我想做的是: 将我的幻灯片视图捕捉到屏幕底部 禁用向上拖动,仅允许向下拖动卡关闭 我所尝试的: 我试图通过将卡片的高度设置为屏幕的高度来改变卡片的大小。您可以看到这一行被注释掉了。这样做之后,我把卡的偏移量弄乱了,并对其进行了设置,使其看起来好像卡实际上小于其大小的一半,大约300高。问题是当我慢慢向上滑动时,我可以看到隐藏在屏幕外的空白区域。这不是我想要的效果 接下来我要做的就是将卡片的高度更改为所需的高度。然后调整偏移量,使卡位于我想要的位置。但是,我觉
import SwiftUI
struct SigninView<Content: View> : View {
@GestureState private var dragState = DragState.inactive
@State var position = CardPosition.top
var content: () -> Content
var body: some View {
let drag = DragGesture()
.updating($dragState) { drag, state, transaction in
state = .dragging(translation: drag.translation)
}
.onEnded(onDragEnded)
return Group {
// Handle()
self.content()
}
.frame(height: 333) //UIScreen.main.bounds.height)
.background(Color.purple)
.cornerRadius(10.0)
.shadow(color: Color(.sRGBLinear, white: 0, opacity: 0.13), radius: 10.0)
.offset(y: self.position.rawValue + self.dragState.translation.height)
.animation(self.dragState.isDragging ? nil : .interpolatingSpring(stiffness: 300.0, damping: 30.0, initialVelocity: 10.0))
.gesture(drag)
}
private func onDragEnded(drag: DragGesture.Value) {
let verticalDirection = drag.predictedEndLocation.y - drag.location.y
let cardTopEdgeLocation = self.position.rawValue + drag.translation.height
let positionAbove: CardPosition
let positionBelow: CardPosition
let closestPosition: CardPosition
if cardTopEdgeLocation <= CardPosition.middle.rawValue {
positionAbove = .top
positionBelow = .middle
} else {
positionAbove = .middle
positionBelow = .bottom
}
if (cardTopEdgeLocation - positionAbove.rawValue) < (positionBelow.rawValue - cardTopEdgeLocation) {
closestPosition = positionAbove
} else {
closestPosition = positionBelow
}
if verticalDirection > 0 {
self.position = positionBelow
} else if verticalDirection < 0 {
self.position = positionAbove
} else {
self.position = closestPosition
}
}
}
enum CardPosition: CGFloat {
case top = 100
case middle = 790
case bottom = 850
}
enum DragState {
case inactive
case dragging(translation: CGSize)
var translation: CGSize {
switch self {
case .inactive:
return .zero
case .dragging(let translation):
return translation
}
}
var isDragging: Bool {
switch self {
case .inactive:
return false
case .dragging:
return true
}
}
}
首先,您可能不应该让
登录视图
成为您的内容视图。相反,请考虑将您的登录视图呈现为<代码>覆盖< /代码>。
var主体:一些视图{
ZStack{
文本(“此处的内容!”)
}
.覆盖(
SigninView()
.抵销(…),
对齐:。底部
)
}
这将自动将您的视图放置在屏幕底部符号视图的高度处,这里应该很少或没有涉及数学。对于偏移量,您将使用手势和希望在底部和覆盖层之间存在的任何空间进行定义
接下来,为了只允许向下的手势,你就不能钳制你的翻译吗
var转换:CGSize{
切换自身{
案例.非活动:
返回,零
案例。拖动(让翻译):
return max(0,translation)//将其钳制为实际的translation或0,这样它就不会变为负值
}
}
您好,叠加看起来效果很好,但我不明白我需要如何处理转换变量。我特别不确定开关语句的最后一种情况是什么。从该位置开始,垂直转换可以是负的,也可以是正的。如果只希望沿一个方向移动,则需要仅将值钳制到该方向。如果向下拖动会产生正向转换,则使用max(0,translation)
。如果向下移动时平移为负数,则需要min(0,translation)
。我在返回最大行上得到一个错误。错误是:无法将“CGSize”类型的值转换为预期的参数类型“Int”,因为它是一个大小。是的,因此您必须钳制高度
值。也许最好在你真正设置它的时候做,而不是要求它。因此,在设置DragGesture
时,在update
函数中,不只是传递原始翻译,而是对height
属性执行上述操作<代码>拖动(平移:drag.translation)
=>。拖动(平移:.init(宽度:drag.translation.width,高度:max(0,drag.translation.height))
。请再次注意哪个方向有效。因此,如果这只允许您向上拖动,请切换到min
,而不是max
。谢谢,这让我更接近我的答案。我简化了代码,除了停止拖动覆盖外,其他一切都正常工作。覆盖让事情变得更容易,但限制了我的工作事实证明,仅仅向下运动是相当困难的。我将用新的代码发布一个新的问题。
import SwiftUI
struct ContentView: View {
@State var show:Bool = false
var body: some View {
SigninView {
VStack {
Text("TESTING")
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.blue)
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}