如何创建对触摸做出反应但将拖动手势传递到下面的视图的透明按钮?

问题描述 投票:0回答:1

我有一个全屏 SpriteKit 场景视图,它可以在其内部处理平移手势。 在它上面,我用 OnTapGesture 覆盖了本机 SwiftUI 视图,它必须对它们的触摸做出反应,但不应干扰平移手势,并将它们传递到下面。

.allowHitTesting(false)
完全消除了对触摸的任何反应,平移手势可以工作,但按钮处理程序不会。

我写了一个小例子来重现我的情况:

import SwiftUI

struct TestView: View
{
    var body: some View
    {
        ZStack
        {
            Rectangle() //simulates spriteKit view
                .fill(.blue)
                .ignoresSafeArea()
                .simultaneousGesture(DragGesture().onChanged(
                    { value in
                        //simulates spriteKit drag handling,
                        //for example animated page flipping
                        print("DragGesture",value.velocity)
                    } ))
                
            HStack(spacing: 0) //my buttons
            {
                Rectangle()
                    .fill(.red.opacity(0.00001))
                    .border(.red, width: 2)
                    .onTapGesture
                    {
                        // this one gets called,
                        // but sk drag gesture is NOT called
                        print("flip page left")
                    }
                
                Rectangle()
                    .fill(.clear)
                    .border(.green, width: 2)
                    .onTapGesture
                    {
                        // this one is NOT called,
                        // and sk gesture is called
                        print("flip page right")
                    }
                
                Button(action:
                        {
                            // this one gets called,
                            // but sk drag gesture is NOT called
                            print("button PRESSED")
                        },
                       label:
                        {
                            Rectangle()
                                .fill(.black)
                                .border(.yellow, width: 2)
                        })
            }
        }
    }
}


#Preview {
    TestView()
}

那么,重申一下:如何制作透明(或 0.0001 不透明度)覆盖按钮来捕获单次触摸,但可以将平移(或拖动)手势传递到其下方的视图?

ios swift user-interface swiftui touch
1个回答
0
投票

根据我的经验,最好单独定义手势,然后根据需要使用它们。这将为将它们与组合手势修饰符(如

.simultaneously
.exclusively
.sequenced
)以及
GestureMask
参数一起使用提供更大的灵活性。

这是修改后的代码供您尝试:

import SwiftUI

struct DragTapTestView: View {
    
    //Gestures
    let dragGesture = DragGesture(minimumDistance: 3)
        .onChanged { value in
            //simulates spriteKit drag handling,
            //for example animated page flipping
            print("DragGesture",value.velocity)
        }
    
    let flipLeftTap =  TapGesture()
        .onEnded { _ in
            print("flip page left")
        }
    
    let flipRightTap =  TapGesture()
        .onEnded { _ in
            print("flip page right")
        }
    
    //Body
    var body: some View {
        ZStack {
            
            //Background with drag gesture
            Rectangle() //simulates spriteKit view
                .fill(.blue)
                .ignoresSafeArea()
                .gesture(dragGesture)
            
            //Buttons
            HStack(spacing: 0) {
                
                //Flip Left
                Color.clear
                    .border(.red, width: 2)
                    .contentShape(Rectangle())
                    .gesture(
                        flipLeftTap
                            .simultaneously(with: dragGesture) //Note this could trigger both a drag and a tap, depending on drag distance and timing
                    )
                
                //Spacer
                Color.clear
                    .border(.green, width: 2)
                
                VStack(spacing: 0) {
                    
                    //Flip Right
                    Color.clear
                        .border(.yellow, width: 2)
                        .contentShape(Rectangle())
                        .gesture(
                            dragGesture
                                .exclusively(before: flipRightTap) //more reliable - compare this with the left tap approach
                        )
                    
                    //Flip Right - Alternate method using a button
                    Button {
                        print("flip right button PRESSED")
                    } label: {
                        Color.clear
                            .border(.orange, width: 2)
                    }
                    .highPriorityGesture(dragGesture, including: .gesture) //Button already has a native tap gesture
                }
            }
        }
    }
}

#Preview {
    DragTapTestView()
}

请注意,向右翻转有两种方法 - 一种使用

Button
,一种不使用。

更重要的是,测试时要注意左右方法的区别。尝试多次拖动左侧区域,您可能会注意到有时它会同时触发拖动和点击。这可能会导致双页翻转,具体取决于您的实现。

将左侧区域的拖动与任何右侧区域的拖动进行比较,后者不应同时触发拖动和点击。

© www.soinside.com 2019 - 2024. All rights reserved.