过去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()
}
}
答案 0 :(得分:1)
首先,您可能不应该将SigninView
成为内容视图。而是考虑将您的登录视图显示为overlay
。
var body: some View {
ZStack {
Text("Content here!")
}
.overlay(
SigninView()
.offset(...),
alignment: .bottom
)
}
这将自动将您的视图放在屏幕底部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
}
}