如何从SwiftUI的形状中创建一个NavigationLink或Button,该按钮仅通过点击形状而不是其框架来触发.



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

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"))
}
}
}

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

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

NavigationLink(destination: Text("DetailView")){
Triangle()
.fill(Color.green)
.frame(width: 100, height: 100, alignment: .center)
}
.contentShape(Triangle())
这里有一个警告,SwiftUI在命中测试中包含一些斜坡,所以这仍然会接受一些点击/触摸接近形状的边界,但仍然在外面。我没有一个很好的办法来处理这些垃圾。但是,你可以看到同样的事情发生在通常构成导航视图的基本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()

}
}
}

请注意,在这个解决方案中,您仍然有点击坡度问题,加上您失去了Button具有的触地/向上高亮显示。

最新更新