用 allowsHitTesting() 禁用交互

1,392 阅读2分钟

译自 www.hackingwithswift.com/books/ios-s…

更多内容,欢迎关注公众号 「Swift花园」

喜欢文章?不如来个 🔺💛➕三连?关注专栏,关注我 🚀🚀🚀

用 allowsHitTesting() 禁用交互

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及计算机编程的相关文章,以及优秀国外文章翻译,欢迎关注~

Swift花园微信公众号