如何在SwiftUI中正确设置可调整的分割视图?

如何在SwiftUI中正确设置可调整的分割视图?,swift,resize,swiftui,drag,splitview,Swift,Resize,Swiftui,Drag,Splitview,这是我第一次尝试SwiftUI,我正在尝试创建一个SwiftUI视图,该视图充当拆分视图,在两个视图的中心有一个可调整的控制柄 下面是我当前的代码实现示例: struct ContentView: View { @State private var gestureTranslation = CGSize.zero @State private var prevTranslation = CGSize.zero var body: some View {

这是我第一次尝试SwiftUI,我正在尝试创建一个SwiftUI视图,该视图充当拆分视图,在两个视图的中心有一个可调整的控制柄

下面是我当前的代码实现示例:

struct ContentView: View {

    @State private var gestureTranslation = CGSize.zero
    @State private var prevTranslation = CGSize.zero

    var body: some View {

        VStack {
            Rectangle()
                .fill(Color.red)
                .frame(height: (UIScreen.main.bounds.height / 2) + self.gestureTranslation.height)
            RoundedRectangle(cornerRadius: 5)
            .frame(width: 40, height: 3)
            .foregroundColor(Color.gray)
            .padding(2)
            .gesture(DragGesture()
                    .onChanged({ value in
                        self.gestureTranslation = CGSize(width: value.translation.width + self.prevTranslation.width, height: value.translation.height + self.prevTranslation.height)

                    })
                    .onEnded({ value in
                        self.gestureTranslation = CGSize(width: value.translation.width + self.prevTranslation.width, height: value.translation.height + self.prevTranslation.height)

                        self.prevTranslation = self.gestureTranslation
                    })
            )
            Rectangle()
                .fill(Color.green)
                .frame(height: (UIScreen.main.bounds.height / 2) - self.gestureTranslation.height)
        }
    }
}
现在是什么样子: [

这是一种工作方式,但是当拖动手柄时,它会非常容易出错,而且似乎需要大量的拖动才能到达某个点


请告诉我哪里出了问题。谢谢。

从我观察到的情况来看,问题似乎来自于手柄在拖动过程中被重新定位。为了抵消这一点,我在手柄上设置了一个反向偏移,使其保持在原来的位置。我试图通过隐藏它来尽可能地掩盖持久的手柄位置其他视图(zIndex)

我希望其他人能更好地解决这个问题。现在,我只有这些:

import PlaygroundSupport
import SwiftUI

struct SplitView<PrimaryView: View, SecondaryView: View>: View {

    // MARK: Props

    @GestureState private var offset: CGFloat = 0
    @State private var storedOffset: CGFloat = 0

    let primaryView: PrimaryView
    let secondaryView: SecondaryView


    // MARK: Initilization

    init(
        @ViewBuilder top: @escaping () -> PrimaryView,
        @ViewBuilder bottom: @escaping () -> SecondaryView)
    {
        self.primaryView = top()
        self.secondaryView = bottom()
    }


    // MARK: Body

    var body: some View {
        GeometryReader { proxy in
            VStack(spacing: 0) {
                self.primaryView
                    .frame(height: (proxy.size.height / 2) + self.totalOffset)
                    .zIndex(1)

                self.handle
                    .gesture(
                        DragGesture()
                            .updating(self.$offset, body: { value, state, _ in
                                state = value.translation.height
                            })
                            .onEnded { value in
                                self.storedOffset += value.translation.height
                            }
                    )
                    .offset(y: -self.offset)
                    .zIndex(0)

                self.secondaryView.zIndex(1)
            }
        }
    }


    // MARK: Computed Props

    var handle: some View {
        RoundedRectangle(cornerRadius: 5)
            .frame(width: 40, height: 3)
            .foregroundColor(Color.gray)
            .padding(2)
    }

    var totalOffset: CGFloat {
        storedOffset + offset
    }
}


// MARK: - Playground

let splitView = SplitView(top: {
    Rectangle().foregroundColor(.red)
}, bottom: {
    Rectangle().foregroundColor(.green)
})

PlaygroundPage.current.setLiveView(splitView)
导入PlaygroundSupport
导入快捷键
结构拆分视图:视图{
//马克:道具
@GestureState专用变量偏移量:CGFloat=0
@国家私有变量storedOffset:CGFloat=0
让primaryView:primaryView
让第二视图:第二视图
//标记:初始化
初始化(
@ViewBuilder顶部:@escaping()->PrimaryView,
@ViewBuilder底部:@escaping()->SecondaryView)
{
self.primaryView=top()
self.secondaryView=bottom()
}
//马克:身体
var body:一些观点{
GeometryReader{中的代理
VStack(间距:0){
自我初步看法
.frame(高度:(proxy.size.height/2)+self.totalOffset)
.zIndex(1)
自我控制
.手势(
德拉格斯特尔()
.updateing(self.$offset,body:{value,state,u}in
状态=value.translation.height
})
.onEnded{中的值
self.storedOffset+=value.translation.height
}
)
.偏移量(y:-自偏移量)
.zIndex(0)
self.secondaryView.zIndex(1)
}
}
}
//马克:电脑道具
var句柄:一些视图{
圆角转角(拐角半径:5)
.框架(宽度:40,高度:3)
.foregroundColor(颜色.灰色)
.填充(2)
}
var totalOffset:CGFloat{
存储偏移量+偏移量
}
}
//马克:操场
让splitView=splitView(顶部:{
矩形().foregroundColor(.red)
},底部:{
矩形().foregroundColor(.green)
})
PlaygroundPage.current.setLiveView(splitView)
只需将代码粘贴到XCode操场/Swift操场中即可

如果您找到了改进我的代码的方法,请告诉我。

有关更简单的解决方案,请参阅

我的看法是:

let MIN_HEIGHT = CGFloat(50)

struct DragViewSizeView: View {
    @State var height: CGFloat = MIN_HEIGHT

    var body: some View {
        VStack {
            Rectangle()
                .fill(Color.red)
                .frame(width: .infinity, height: height)

            HStack {
                Spacer()
                Rectangle()
                    .fill(Color.gray)
                    .frame(width: 100, height: 10)
                    .cornerRadius(10)
                    .gesture(
                        DragGesture()
                            .onChanged { value in
                                height = max(MIN_HEIGHT, height + value.translation.height)
                            }
                    )
                Spacer()
            }

            VStack {
                Text("my o my")
                Spacer()
                Text("hoo hah")
            }
        }
    }
}

struct DragTestView: View {

    var body: some View {
        VStack {
            DragViewSizeView()

            Spacer() // If comment this line the result will be as on the bottom GIF example
        }
    }
}

struct DragTestView_Previews: PreviewProvider {
    static var previews: some View {
        DragTestView()
    }
}

以前我有点放弃了这个问题,但现在我从你那里得到了答案,我认为重新审视这个问题会很好。事实上,这个解决方案似乎不是最好的,因为句柄在拖动结束之前会“消失”。我将对它进行研究,看看如何改进它。我对两个代码都进行了研究,我发现实际上在我的代码中,如果我将
DragGesture()
更改为
DragGesture(coordinateSpace:.global)
则故障似乎会消失!因为您的解决方案确实有效,而且它确实间接地让我找到了符合我需要的解决方案,所以我会将此标记为已解决。如果您使用
DragGesture(coordinateSpace:.global)
然后可以删除手柄的反向偏移(
.offset(y:-self.offset)
),然后一切都会正常运行。