I'm a decade iOS veteran but new to Swift/SwiftUI so please be gentle. One thing I'm confused about is why a View (I've tried a few but let's use TextView() for example) appears to not be drawn if the opacity is set to zero or the .background(Color.clear).
What I'm trying to accomplish is to put two buttons in an HStack as the first member in a ZStack (so "back" most) in order to determine when the user double taps the left side of the screen or the right, but I don't want anything to actually be shown, just detect the taps. My hackish solution is to set opacity to 0.001. With that opacity setting nothing is visible and I can detect with .onTapGesture(count:2) but surely this isn't the optimal way. In UIKit land I'd be tempted to just process the tap coordinate myself using screen dimensions to determine which side it landed on, but I don't think that's terribly "swifty" even if it's possible without wrapping UIKit classes. Trying to learn, so doing everything as "pure SwiftUI" as possible.
public var body: some View {
ZStack {
HStack {
VStack {
Text("").frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.blue)
.opacity(0.0001) //hack workaround, setting opacity to 0.0 and it's like the view isn't even drawn or present (the onTapGesture doesn't get recognized because the VStack has no size when the Text frame is zero and that's the only point! Interestingly setting the background to Color.clear creates the same issue
}.onTapGesture(count: 2) {
print("got a double tap on the LEFT side scroll button")
}
VStack {
Text("").frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.yellow)
.opacity(0.0001)//hack workaround, setting opacity to 0.0 and it's like the view isn't even drawn or present (the onTapGesture doesn't get recognized because the VStack has no size when the Text frame is zero and that's the only point! Interestingly setting the background to Color.clear creates the same issue
}.onTapGesture(count: 2) {
print("got a double tap on the RIGHT side scroll button")
}
}
[subsequent members of the ZStack removed as they're not relevant to the question]
}
}
I guess my questions are:
a) what to use that's invisible but still layed out to detect onTapGesture?
b) some knowledge about why Text() and other views basically don't exist if opacity is zero or background is set to clear?
Thanks!
CodePudding user response:
a) what to use that's invisible but still layed out to detect onTapGesture?
We can use .contentShape
modifier to make any area, even completely transparent, tappable (aka hit-testable), like:
Color.clear
.frame(width: 100, height: 100)
.contentShape(Rectangle())
.onTapGesture {
print(">>> Tapped!")
}
b) some knowledge about why Text() and other views basically don't exist if opacity is zero or background is set to clear?
SwiftUI renders views into one context (it is opposite to UIKit where every UIView view renders itself), so when view is completely transparent there is nothing to render.