如何禁用 SwiftUI 视图中的用户交互?

假设我有一个 SwiftUI 视图层次结构如下:

ZStack() {
ScrollView {
...
}
Text("Hello.")
}

Text视图阻止触摸事件到达底层 ScrollView

使用 UIKit 时,我会使用类似 .isUserInteractionEnabled的工具来控制它,但是我找不到任何方法来使用 SwiftUI 来实现这一点。

我试过在文本视图中添加一个 GestureGestureMask.none,但似乎不起作用。

我希望我在这里遗漏了一些明显的东西,因为我需要在滚动视图的顶部放置一些状态信息。

36039 次浏览

There is a modifier on View to disable or enable user interaction:

disabled(_ disabled: Bool)

This is most likely a bug in SwiftUI, but the workaround for this problem was to remove a .border() that I had put on the Text view for bounds debugging.

What about using the .allowsHitTesting()?

https://developer.apple.com/documentation/swiftui/image/3269586-allowshittesting

From my understanding it should pass the gesture to the view behind if it's disabled.

ZStack() {
ScrollView {
...
}
Text("Hello.").allowsHitTesting(false)
}

You want to make sure you fill your view with some color, except Clear color (you can always change opacity). I've also added blur to hide elements. Here's what worked for me:

SwiftUI:

ZStack{
SomeView().blur(radius: 12)
Rectangle()
.fill(Color.white.opacity(0))
.allowsHitTesting(false)
}

Another way to disable user interactions like scroll or button taps, but attach an action to user taps (for example a message to users that this feature is coming or behind a paywall):

SwiftUI:

VStack{
SomeView().blur(radius: 12)
}
.contentShape(Rectangle())
.onTapGesture {
print("No access!")
}

SwiftUI 2.0

 ZStack {


// Your Stack to Disable User Interaction


}.disabled(showLoadingIndicator)

Certain elements inside of SwiftUI cannot be disabled through .disabled or .allowHitTesting. A major HACK is to wrap your element in a TabView and apply a paging style to it. Again this is a major hack but it's an interesting solution I'm using currently.

I'm doing something similar on a watch app, .overlaying a text field over a Slider. I couldn't get either .disable or .allowHitTesting to work when applied to the Text field.

To solve this, I found that placing the Text field in a Group{} (all by itself) and then applying the .allowHitTesting(false) worked perfectly.

Put your view to be "tap disabled" into a Group then apply the modifier .allowsHitTesting(false) to disable interaction with any view inside the group.

Group {
Button("Hello")
}
.allowsHitTesting(false)

To enable interaction switch the modifier to true.