【问题标题】:How to create a NavigationLink or Button from a shape in SwiftUI that is only triggered by tapping on the shape but not its frame如何从 SwiftUI 中的形状创建 NavigationLink 或 Button,仅通过点击形状而不是其框架触发
【发布时间】:2021-01-19 21:49:25
【问题描述】:

我有一个简单的形状,我想用作按钮,但我希​​望链接/按钮仅在单击形状本身而不是在其框架上时触发。使用以下代码,在三角形框架内单击时也会触发链接:

struct Triangle: Shape {
    func path(in rect: CGRect)-> Path {
        var path = Path()

        path.move(to: CGPoint(x: rect.midX, y: rect.minY))
        path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
        path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
        path.addLine(to: CGPoint(x: rect.midX, y: rect.minY))

        return path
    }
}
struct ContentView: View {
    var body: some View {
        NavigationView {
            NavigationLink(
                destination: Text("DetailView")){
                Triangle()
                    .fill(Color.green)
                    .frame(width: 200, height: 200, alignment: .center)
            }.navigationBarTitle(Text("Triangle"))
        }
    }
}

如何将代码调整为只点击三角形而不是触发链接的框架?

【问题讨论】:

    标签: swift button swiftui shapes swiftui-navigationlink


    【解决方案1】:

    您可以添加contentShape 修饰符来告诉系统如何对 NavigationLink 进行命中测试:

    NavigationLink(destination: Text("DetailView")){
        Triangle()
            .fill(Color.green)
            .frame(width: 100, height: 100, alignment: .center)
    }
    .contentShape(Triangle())
    

    这里有一个警告,即 SwiftUI 在点击测试中包含一些 slop,因此它仍然会接受一些 接近形状边界但仍在外部的点击/触摸。我没有一个很好的解决方案来摆脱这种污点。但是,您可以看到同样的事情发生在基本的Rectangle 上,它通常也构成导航视图——例如在其周围放置一个border,并注意您仍然可以在该边界之外轻轻点按。

    您可以尝试的第二种方法是单独渲染Path,将onTapGesture 附加到它,然后打开/关闭连接到NavigationLink 的布尔值,然后您想将其移出您的等级制度。比如:

    struct ContentView: View {
        @State var navigationLinkActive = false
        
        var body: some View {
            NavigationView {
                Group {
                    if navigationLinkActive {
                        NavigationLink(destination: Text("Detail"), isActive: $navigationLinkActive) {
                            EmptyView()
                        }
                    }
                    Triangle()
                        .fill(Color.green)
                        .frame(width: 100, height: 100, alignment: .center)
                        .onTapGesture {
                            navigationLinkActive = true
                        }
                }.navigationBarTitle(Text("Triangle"))
                
                
                EmptyView()
                
            }
        }
    }
    

    请注意,在此解决方案中,您仍然会遇到 hit slop 问题,加上您会失去Button 所具有的触地/向上突出显示。

    【讨论】:

    • 非常感谢! .contentShape 修饰符是我正在寻找的。在第一次测试中,它对我来说效果很好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多