SwiftUI 中 DragGesture() 的高度计算不正确

Incorrect height calculation with DragGesture() in SwiftUI

我正在使用 SwiftUI 开发一个基于地图的应用程序,我需要通过拖动它来更改模态卡片(这是地图信息所在的视图)的高度 up/down,就像在 Apple 中一样地图。

这是我尝试与之交互的高度的卡片的屏幕截图 https://i.stack.imgur.com/mZX2m.png

我用 RoundedRectangle 实现了 ZStack 并添加了 DragGesture() 修饰符。

            ZStack(alignment: .top){
                RoundedRectangle(cornerRadius: 16.0)
                    .frame(height:currentHeight)
                Text("Card")
                    .font(.title)
                    .fontWeight(.bold)
                    .foregroundColor(Color.white)
                    .multilineTextAlignment(.center)
                    .padding(.top)
            }.gesture(DragGesture()
                .onChanged { value in
                    if (self.currentHeight + value.predictedEndLocation.y - value.startLocation.y > UIScreen.main.bounds.height) {
                        self.currentHeight = UIScreen.main.bounds.height
                    } else {
                        self.currentHeight += value.predictedEndLocation.y - value.startLocation.y
                    }
                }
                .onEnded { value in
                    if (self.currentHeight + value.predictedEndLocation.y - value.startLocation.y > UIScreen.main.bounds.height) {
                        self.currentHeight = UIScreen.main.bounds.height
                    } else {
                        self.currentHeight += value.predictedEndLocation.y - value.startLocation.y
                    }
                })

第一个问题是向上拖动,卡片超过屏幕高度,我正在检查 UIScreen 边界高度以防止高度大于屏幕,但是计算有更多问题,卡片的高度很快变得不明确并且它不想拖累。

我从未使用过手势识别器。能告诉我正确的计算方法吗?

谢谢!

这是一种方法(下面代码中的一些有用的注释)

struct TestResizingCard: View {

    static let kMinHeight: CGFloat = 100.0
    @State var currentHeight: CGFloat = kMinHeight // << any initial

    var body: some View {
        GeometryReader { g in // << for top container height limit
            ZStack(alignment: .bottom) {
                Rectangle().fill(Color.yellow) // << just for demo

                self.card()
                .gesture(DragGesture()
                    .onChanged { value in
                        // as card is at bottom the offset is reversed
                        let newHeight = self.currentHeight - (value.location.y - value.startLocation.y)
                        if newHeight > Self.kMinHeight && newHeight < g.size.height {
                            self.currentHeight = newHeight
                        }
            })
            }
        }
    }

    func card() -> some View {
        ZStack(alignment: .top){
            RoundedRectangle(cornerRadius: 16.0)
                .frame(height:currentHeight)
            Text("Card")
                .font(.title)
                .fontWeight(.bold)
                .foregroundColor(Color.white)
                .multilineTextAlignment(.center)
                .padding(.top)
        }
    }
}

struct TestResizingCard_Previews: PreviewProvider {
    static var previews: some View {
        TestResizingCard()
    }
}