Cocoa touch 如何在SwiftUI中将拖动手势限制为仅一个方向?

Cocoa touch 如何在SwiftUI中将拖动手势限制为仅一个方向?,cocoa-touch,swiftui,ios13,Cocoa Touch,Swiftui,Ios13,我尴尬地花了两周的时间来解决这个问题 我想做的是: 将我的幻灯片视图捕捉到屏幕底部 禁用向上拖动,仅允许向下拖动卡关闭 我所尝试的: 我试图通过将卡片的高度设置为屏幕的高度来改变卡片的大小。您可以看到这一行被注释掉了。这样做之后,我把卡的偏移量弄乱了,并对其进行了设置,使其看起来好像卡实际上小于其大小的一半,大约300高。问题是当我慢慢向上滑动时,我可以看到隐藏在屏幕外的空白区域。这不是我想要的效果 接下来我要做的就是将卡片的高度更改为所需的高度。然后调整偏移量,使卡位于我想要的位置。但是,我觉

我尴尬地花了两周的时间来解决这个问题

我想做的是:

  • 将我的幻灯片视图捕捉到屏幕底部
  • 禁用向上拖动,仅允许向下拖动卡关闭
  • 我所尝试的:

    我试图通过将卡片的高度设置为屏幕的高度来改变卡片的大小。您可以看到这一行被注释掉了。这样做之后,我把卡的偏移量弄乱了,并对其进行了设置,使其看起来好像卡实际上小于其大小的一半,大约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()
        }
    }