I have a SwiftUI app where some content is presented to the user, and then the user will annotate over it with a Path
view.
The issue I have is that when I use a clear background for the drawing view, or no background at all, the content beneath it will appear as desired, but the gesture changes for the drawing action do not register.
If however, I assign a non-clear color for the background, then the gesture changes register and the drawing appears.
FWIW, I was able to achieve the desired effect using a UIKit
based interface, and would just like to recreate it with SwiftUI now.
The simplified code below is a complete example that demonstrates my predicament. This is just an approximation of the code in use, so it's not exactly production quality.
By changing backgroundColor
to clear
or by commenting out the .background(self.backgroundColor)
line, the BackgroundView
will now appear, but onChanged
does not get called, so no ink will appear.
If I run as is, then the ink will appear, but I cannot see the BackgroundView
.
import SwiftUI
struct ContentView: View {
var body: some View {
GeometryReader { geometry in
ZStack {
DrawingView(backgroundColor: .white,
geometry: geometry)
.zIndex(1)
BackgroundView()
}
}
}
}
struct DrawingView: View {
let backgroundColor: Color
let geometry: GeometryProxy
@State private var points = [CGPoint]()
var body: some View {
Path { path in
guard !points.isEmpty else { return }
for index in 0..<points.count - 1 {
path.move(to: points[index])
path.addLine(to: points[index + 1])
}
}
.stroke(Color.red, lineWidth: 3.0)
.background(self.backgroundColor)
.gesture(DragGesture(minimumDistance: 0.1)
.onChanged({ changeValue in
print("onChanged called")
self.points.append(changeValue.location)
}))
}
}
// Just a simple View to fill the background
struct BackgroundView: View {
var body: some View {
Color.black
.edgesIgnoringSafeArea(.all)
}
}
Instead of background use .contentShape as
.stroke(Color.red, lineWidth: 3.0)
.contentShape(Rectangle()) // << here !!
.gesture(DragGesture(minimumDistance: 0.1)
.onChanged({ changeValue in