译自 www.hackingwithswift.com/books/ios-s…
更多内容,欢迎关注公众号 「Swift花园」
喜欢文章?不如来个 🔺💛➕三连?关注专栏,关注我 🚀🚀🚀
SwiftUI 有一套高级的点击测试算法,既用于视图的 frame,也用于视图的内容。例如,如果你给某个文本视图添加了一个点击手势,那么文本视图的所有部分都会变成可点击的 —— 你不会因为刚好点击在一个空格的位置而让点击穿透文本视图。另一方面,如果你给一个圆添加相同的手势,SwiftUI 会自动忽略 frame 中透明的部分。
我们用一个盖在矩形上的圆来演示,两个形状都添加了 onTapGesture()
modifier:
ZStack { Rectangle() .fill(Color.blue) .frame(width: 300, height: 300) .onTapGesture { print("矩形被点击!") } Circle() .fill(Color.red) .frame(width: 300, height: 300) .onTapGesture { print("圆被点击!") } } 复制代码
尝试运行一下,你会发现,当你点击在圆内部时,打印 “圆被点击!”,但点击在圆外,矩形内时则打印 “矩形被点击!” —— 尽管圆的 frame 和矩形的 frame 是一样大的。
对于控制用户交互,SwiftUI 提供了两张方式,第一种就是 allowsHitTesting()
modifier。当它被添加到视图并且参数被设置为 false
时,视图被认为是不可点击的。 这并不是视图吃掉了点击事件,它只是不捕获任何点击 —— 点击会直接穿透到它后面的视图。
把圆的代码改成下面这样:
Circle() .fill(Color.red) .frame(width: 300, height: 300) .onTapGesture { print("圆被点击!") } .allowsHitTesting(false) 复制代码
这时再点击圆会打印 “矩形被点击!”,因为圆已经拒绝响应点击。
另外一个控制交互的方式是使用 contentShape()
modifier,它可以让我们指定可点击区域的形状。对于圆来说,默认的可点击形状就是相同的圆,但你可以像下面这样指定一个不同的形状:
Circle() .fill(Color.red) .frame(width: 300, height: 300) .contentShape(Rectangle()) .onTapGesture { print("圆被点击!") } 复制代码
contentShape()
modifier 在针对包含 Spacer
的栈应用的点击动作时十分有用,因为默认情况下,SwiftUI 不会在栈里的某个 spacer 被点击时触发动作。
下面是代码:
VStack { Text("Hello") Spacer().frame(height: 100) Text("World") } .onTapGesture { print("VStack被点击!") } 复制代码
运行代码,你会发现你可以点击 “Hello” 标签和 “World” 标签,但不能点击它们之前的 spacer。不过,通过在 VStack
上应用 contentShape(Rectangle())
,你可以让整个 VStack
变成可点击的,包括 spacer 在内:
VStack { Text("Hello") Spacer().frame(height: 100) Text("World") } .contentShape(Rectangle()) .onTapGesture { print("VStack被点击!") } 复制代码
我的公众号 这里有Swift及计算机编程的相关文章,以及优秀国外文章翻译,欢迎关注~