gpt4 book ai didi

cocoa-touch - 如何在 SwiftUI 中将拖动手势限制在一个方向上?

转载 作者:行者123 更新时间:2023-12-05 05:08:26 27 4
gpt4 key购买 nike

过去 2 周我一直很尴尬地试图解决这个问题。

我想做的是:

  1. 将我的幻灯片 View 对齐到屏幕底部
  2. 禁止向上拖动,只允许向下拖动卡片以关闭

我尝试过的:

我尝试通过将卡片的高度设置为屏幕的高度来调整卡片的大小。你可以看到这一行被注释掉了。这样做之后,我弄乱了卡片的偏移量并将其设置为看起来卡片实际上小于其大小的一半,高度约为 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
}
}
}

这是我的 ContentView 页面,我在其中对其进行了测试:

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()
}
}

最佳答案

首先,您可能不应该让 SigninView 成为您的内容 View 。相反,请考虑将您的登录 View 显示为 overlay

var body: some View {
ZStack {
Text("Content here!")
}
.overlay(
SigninView()
.offset(...),
alignment: .bottom
)
}

这会自动将您的 View 放置在屏幕底部与您的 SigninView 高度相同的位置,这里几乎不涉及任何数学运算。偏移量,您将使用您的手势以及您希望在底部和覆盖层之间存在的任何空间来定义。

接下来,为了只允许向下手势,你不能只限制你的翻译吗?

    var translation: CGSize {
switch self {
case .inactive:
return .zero
case .dragging(let translation):
return max(0, translation) // clamp this to the actual translation or 0 so it can't go negative
}
}

关于cocoa-touch - 如何在 SwiftUI 中将拖动手势限制在一个方向上?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58328540/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com