Skip to content

Instantly share code, notes, and snippets.

@ryohey
Created August 4, 2023 05:15
Show Gist options
  • Save ryohey/a0a0645477aacb65f49f16b776a39707 to your computer and use it in GitHub Desktop.
Save ryohey/a0a0645477aacb65f49f16b776a39707 to your computer and use it in GitHub Desktop.
import SwiftUI
extension View {
/// By reducing the hit detection, make it so that tap detection occurs within the range of the frame
///
/// In SwiftUI, a View within about 10pt radius from the tap position is detected as touch,
/// so we place a contentShape that is just as small.
func exactHitArea() -> some View {
modifier(ExactHitAreaModifier())
}
}
private struct ExactHitAreaModifier: ViewModifier {
private let hitAreaPadding: CGFloat = 10
@State private var size: CGSize?
func body(content: Content) -> some View {
let scale = size.map {
CGPoint(
x: ($0.width - hitAreaPadding * 2) / $0.width,
y: ($0.height - hitAreaPadding * 2) / $0.height
)
} ?? .zero
content
.contentShape(Rectangle().scale(x: scale.x, y: scale.y))
.overlay {
GeometryReader { proxy in
Color.clear
.onAppear {
self.size = proxy.size
}
.onChange(of: proxy.size) { newValue in
self.size = newValue
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment