SwiftUI:禁止用户交互

SwiftUI具有先进的点击测试算法,该算法不仅用于视图的Frame,而且还应用于其内容。例如,如果您向文本视图添加轻击手势,则文本视图的所有部分都是可点击的——除了碰巧恰好点到了空白部分。另一方面,如果您将相同的手势附加到圆上,则SwiftUI将忽略圆的透明部分。

为了说明这一点,这是一个使用ZStack与矩形重叠的圆,它们都带有onTapGesture()修饰符:

ZStack {
    Rectangle()
        .fill(Color.blue)
        .frame(width: 300, height: 300)
        .onTapGesture {
            print("Rectangle tapped!")
        }

    Circle()
        .fill(Color.red)
        .frame(width: 300, height: 300)
        .onTapGesture {
            print("Circle tapped!")
        }
}

如果您尝试一下,您会发现在圆内轻按会打印“Circle tapped!”,但是在圆圈后面的矩形上会打印“Rectangle tapped!” ——即使该圆实际上与矩形具有相同的 Frame。

SwiftUI使我们可以通过两种有用的方式来控制用户交互,第一种是allowHitTesting()修饰符。如果将参数设置为 false,并其附加到视图,则该视图甚至都不被视为可点击的。但是,这并不意味着它是没有处理点击的,只是它不会捕获任何点击——而是会轻按视图后面的内容。

尝试将其添加到我们的圆中,如下所示:

Circle()
    .fill(Color.red)
    .frame(width: 300, height: 300)
    .onTapGesture {
        print("Circle tapped!")
    }
    .allowsHitTesting(false)

现在,轻按圆将始终打印“Rectangle tapped!”,因为该圆将拒绝响应轻敲。

控制用户交互性的另一种有用方法是使用contentShape()修饰符,它使我们可以为某些东西指定可点击的形状。默认情况下,圆的可点击形状是相同大小的圆,但是您可以这样指定其他形状:

Circle()
    .fill(Color.red)
    .frame(width: 300, height: 300)
    .contentShape(Rectangle())
    .onTapGesture {
        print("Circle tapped!")
    }

当您点击带有分隔符(Spacer())的堆栈时,contentShape()修饰符真正有用的地方是因为默认情况下,当点击堆栈分隔符时,SwiftUI不会触发动作。

您可以尝试以下示例:

VStack {
    Text("Hello")
    Spacer().frame(height: 100)
    Text("World")
}
.onTapGesture {
    print("VStack tapped!")
}

如果您运行该程序,将会找到“Hello”标签和“World”标签,但不能点击两者之间的空格。但是,如果我们在VStack上使用contentShape(Rectangle()),则堆栈的整个区域都可以被轻敲,包括间隔符:

VStack {
    Text("Hello")
    Spacer().frame(height: 100)
    Text("World")
}
.contentShape(Rectangle())
.onTapGesture {
    print("VStack tapped!")
}

译自 Disabling user interactivity with allowsHitTesting()

你可能感兴趣的:(SwiftUI:禁止用户交互)