Skip to content

Instantly share code, notes, and snippets.

@mdb1
Created October 22, 2023 15:02
Show Gist options
  • Save mdb1/4680d796b91c370eb07ba6f6da1d6775 to your computer and use it in GitHub Desktop.
Save mdb1/4680d796b91c370eb07ba6f6da1d6775 to your computer and use it in GitHub Desktop.
TapShrinkModifier
import SwiftUI
extension View {
/// Adds the `TapShrinkModifier` modifier.
/// A modifier that adds a shrink animation on tap.
/// - Parameters:
/// - animationDuration: The shrink animation duration. `Default = 0.3`.
/// - shrinkScale: The scale value for when the view is pressed. `Default = 0.85`.
/// - defaultScale: The scale value for when the view is not pressed: `Default = 1.0`.
/// - action: The action to execute.
/// - Returns: The original view, with the modifier applied.
func shrinkOnTap(
animationDuration: TimeInterval = 0.3,
shrinkScale: CGFloat = 0.85,
defaultScale: CGFloat = 1,
action: @escaping () -> Void
) -> some View {
modifier(
TapShrinkModifier(
animationDuration: animationDuration,
shrinkScale: shrinkScale,
defaultScale: defaultScale,
action: action
)
)
}
}
struct TapShrinkModifier: ViewModifier {
@State private var isTouched = false
private var animationDuration: TimeInterval
private var shrinkScale: CGFloat
private var defaultScale: CGFloat
private var action: () -> Void
init(
animationDuration: TimeInterval,
shrinkScale: CGFloat,
defaultScale: CGFloat,
action: @escaping () -> Void
) {
self.animationDuration = animationDuration
self.shrinkScale = shrinkScale
self.defaultScale = defaultScale
self.action = action
}
func body(content: Content) -> some View {
content
.scaleEffect(isTouched ? shrinkScale : defaultScale, anchor: .center)
.animation(.easeInOut(duration: animationDuration), value: isTouched)
.gesture(
DragGesture(minimumDistance: 0)
.onChanged { _ in isTouched = true }
.onEnded { _ in
isTouched = false
action()
}
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment