Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/100.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 在SwiftUI中,如何在容器视图外使手势处于非活动状态?_Ios_Swiftui_Gesture_Clipping - Fatal编程技术网

Ios 在SwiftUI中,如何在容器视图外使手势处于非活动状态?

Ios 在SwiftUI中,如何在容器视图外使手势处于非活动状态?,ios,swiftui,gesture,clipping,Ios,Swiftui,Gesture,Clipping,我试图使视图仅在其剪裁容器视图内可拖动和/或缩放(否则它可能会与其他视图的手势发生冲突),但到目前为止,我所做的任何尝试都无法阻止手势延伸到容器的可见边界之外 下面是我不想要的行为的简化演示 当红色矩形部分超出绿色VStack区域(剪裁)时,它会响应超出绿色区域的拖动手势: 如何将此手势限制为仅在容器内工作(上例中为绿色区域) 更新: @Asperi对上述问题的解决方案效果很好,但当我在上面的容器旁边添加第二个可拖动的容器时,我在第一个容器中得到了一个无法拖动的“死区”(如果没有剪裁,第二个正

我试图使视图仅在其剪裁容器视图内可拖动和/或缩放(否则它可能会与其他视图的手势发生冲突),但到目前为止,我所做的任何尝试都无法阻止手势延伸到容器的可见边界之外

下面是我不想要的行为的简化演示

当红色矩形部分超出绿色VStack区域(剪裁)时,它会响应超出绿色区域的拖动手势:

如何将此手势限制为仅在容器内工作(上例中为绿色区域)

更新: @Asperi对上述问题的解决方案效果很好,但当我在上面的容器旁边添加第二个可拖动的容器时,我在第一个容器中得到了一个无法拖动的“死区”(如果没有剪裁,第二个正方形似乎会覆盖第一个正方形)。问题只发生在原始/左侧,而不是新的一侧。我认为这与它有更高的优先级有关,因为它排在第二位

以下是新问题的说明:

以下是更新后的代码:

struct ContentView: View {
    
    @State var position1: CGPoint = CGPoint(x: 100, y: 150)
    @State var lastPosition1: CGPoint = CGPoint(x: 100, y: 150)
    let dragArea1: CGRect = CGRect(x: 0, y: 0, width: 200, height: 300)
    
    @State var position2: CGPoint = CGPoint(x: 100, y: 150)
    @State var lastPosition2: CGPoint = CGPoint(x: 100, y: 150)
    let dragArea2: CGRect = CGRect(x: 0, y: 0, width: 200, height: 300)
    
    var body: some View {

        let drag1 = DragGesture(coordinateSpace: .named("dragArea1"))
        .onChanged {
            guard self.dragArea1.contains($0.startLocation) else { return }
            self.position1 = CGPoint(x: $0.translation.width + self.lastPosition1.x, y: $0.translation.height + self.lastPosition1.y)
        }
        .onEnded {_ in
            self.lastPosition1 = self.position1
        }
        
        let drag2 = DragGesture(coordinateSpace: .named("dragArea2"))
        .onChanged {
            guard self.dragArea2.contains($0.startLocation) else { return }
            self.position2 = CGPoint(x: $0.translation.width + self.lastPosition2.x, y: $0.translation.height + self.lastPosition2.y)
        }
        .onEnded {_ in
            self.lastPosition2 = self.position2
        }
        
        return HStack {
            VStack {
                Rectangle().foregroundColor(.red)
                    .frame(width: 150, height: 150)
                    .position(self.position1)
                    .gesture(drag1)
                    .clipped()
            }
            .background(Color.green)
            .frame(width: dragArea1.width, height: dragArea1.height)
            
            VStack {
                Rectangle().foregroundColor(.blue)
                .frame(width: 150, height: 150)
                .position(self.position2)
                .gesture(drag2)
                .clipped()
            }
            .background(Color.yellow)
            .frame(width: dragArea2.width, height: dragArea2.height)
        }
        
    }
}

关于如何保持在任何容器外禁用拖动的想法,如已实现的,但也允许在每个容器的完整边界内拖动,而不管其他容器发生了什么?

这里是可能的解决方案。其思想是在容器坐标空间中设置拖动坐标,如果开始位置超出指定区域,则忽略拖动

使用Xcode 11.4/iOS 13.4进行测试

对于第二部分(即原始问题的更新),以下是我的结论。基本上,我将两个单独的拖动手势组合成一个涵盖整个HStack的手势,然后根据HStack的起始位置将该手势指向相应的@State变量

结果演示:

代码:

struct ContentView:View{
@状态变量位置1:CGPoint=CGPoint(x:100,y:150)
@状态变量lastPosition1:CGPoint=CGPoint(x:100,y:150)
让dragArea1:CGSize=CGSize(宽:200,高:300)
@状态变量位置2:CGPoint=CGPoint(x:100,y:150)
@状态变量lastPosition2:CGPoint=CGPoint(x:100,y:150)
让dragArea2:CGSize=CGSize(宽:200,高:300)
var body:一些观点{
让drag=DragGesture()
.一旦改变{

guard$0.startLocation.y>=0&&$0.startLocation.y两天来,我一直在寻找类似问题的解决方案 @Asperi的解决方案很有帮助,但对于3位数或更多的数字,它并不通用

我的解决方案是:添加

.contentShape(Rectangle())
以前

.gesture(DragGesture().onChanged {
这篇文章帮助了我。

我希望它对某人有用

示例代码:

var body: some View {
        VStack {
            Image("my image")
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(200, 200)

                .clipShape(Rectangle())
                .contentShape(Rectangle())   // <== this code helped me

                .gesture(
                    DragGesture()
                        .onChanged {
                            //
                        }
                        .onEnded {_ in
                            //
                        }
                )
        }
}
var主体:一些视图{
VStack{
图像(“我的图像”)
.可调整大小()
.aspectRatio(内容模式:.fit)
.框架(200200)
.clipShape(矩形())

.contentShape(矩形())//非常感谢,@Asperi!这是一个非常优雅的问题解决方案,正如所发布的那样,效果非常好。我已经用一个后续问题更新了这个问题,该问题是由于将两个可拖动区域相邻而产生的。请看一看,并让我知道您是否有解决此问题的好主意。非常感谢!好的,我解决了如何完成第二部分。我将把我的工作作为一个单独的答案发布。再次感谢,@Asperi!它工作很好,但它很难看,因为你无法隔离每个组件内部的行为。我需要这些组件的网格,我不想在一个超级视图中管理它们。每个组件都应该包含自己的行为r、 您的答案不清楚,请重新格式化您的帖子,您的代码中使用了大量不必要的空格和未闭合的括号。请重新格式化您的代码以获得完整的工作版本。您可以阅读,应该看起来像。我编辑了我的答案
.contentShape(Rectangle())
.gesture(DragGesture().onChanged {
var body: some View {
        VStack {
            Image("my image")
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(200, 200)

                .clipShape(Rectangle())
                .contentShape(Rectangle())   // <== this code helped me

                .gesture(
                    DragGesture()
                        .onChanged {
                            //
                        }
                        .onEnded {_ in
                            //
                        }
                )
        }
}
struct ContentView: View {

@State var position1: CGPoint = CGPoint(x: 100, y: 150)
@State var lastPosition1: CGPoint = CGPoint(x: 100, y: 150)
let dragArea1: CGSize = CGSize(width: 200, height: 300)

@State var position2: CGPoint = CGPoint(x: 100, y: 150)
@State var lastPosition2: CGPoint = CGPoint(x: 100, y: 150)
let dragArea2: CGSize = CGSize(width: 200, height: 300)

var body: some View {
    
let drag = DragGesture()
    .onChanged {
        if $0.startLocation.x <= self.dragArea1.width {
            self.position1 = CGPoint(x: $0.translation.width + self.lastPosition1.x, y: $0.translation.height + self.lastPosition1.y)
        } else {
            self.position2 = CGPoint(x: $0.translation.width + self.lastPosition2.x, y: $0.translation.height + self.lastPosition2.y)
        }
    }
    .onEnded {_ in
        self.lastPosition1 = self.position1
        self.lastPosition2 = self.position2
    }
    
    return HStack {
        VStack {
            Rectangle().foregroundColor(.red)
                .frame(width: 150, height: 150)
                .position(self.position1)
                .clipped()
        }
        .background(Color.green)
        .frame(width: dragArea1.width, height: dragArea1.height)
        
        VStack {
            Rectangle().foregroundColor(.blue)
            .frame(width: 150, height: 150)
            .position(self.position2)
            .clipped()
        }
        .background(Color.yellow)
        .frame(width: dragArea2.width, height: dragArea2.height)
    }
    .clipShape(Rectangle())     //<=== This
    .contentShape(Rectangle())  //<=== and this
    .gesture(drag)
} }