How to disable user interaction on SwiftUI view?
SwiftSwiftuiUser InteractionSwift Problem Overview
Let's say I have a SwiftUI view hierarchy that looks like this:
ZStack() {
ScrollView {
...
}
Text("Hello.")
}
The Text
view blocks touch events from reaching the underlying ScrollView
.
With UIKit, I'd use something like .isUserInteractionEnabled
to control this, but I can't find any way to do this with SwiftUI.
I've tried adding a Gesture
with a GestureMask
of .none
on the text view, but that doesn't seem to work.
I hope I'm missing something obvious here, because I need to put some status information on top of the scroll view.
Swift Solutions
Solution 1 - Swift
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)
}
Solution 2 - Swift
There is a modifier on View to disable or enable user interaction:
disabled(_ disabled: Bool)
Solution 3 - Swift
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!")
}
Solution 4 - Swift
SwiftUI 2.0
ZStack {
// Your Stack to Disable User Interaction
}.disabled(showLoadingIndicator)
Solution 5 - Swift
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.
Solution 6 - Swift
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.
Solution 7 - Swift
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.