How to disable user interaction on SwiftUI view?

SwiftSwiftuiUser Interaction

Swift 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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionchockenberryView Question on Stackoverflow
Solution 1 - SwiftMihaiLView Answer on Stackoverflow
Solution 2 - SwiftLuLuGaGaView Answer on Stackoverflow
Solution 3 - SwiftReposeView Answer on Stackoverflow
Solution 4 - SwiftThreadripperView Answer on Stackoverflow
Solution 5 - SwiftchockenberryView Answer on Stackoverflow
Solution 6 - SwiftnoobularView Answer on Stackoverflow
Solution 7 - SwiftBarryDView Answer on Stackoverflow