Skip to content

Instantly share code, notes, and snippets.

@gabrieltheodoropoulos
Created November 1, 2020 17:56
Show Gist options
  • Select an option

  • Save gabrieltheodoropoulos/59dc104163b5718018c6c55309b110fb to your computer and use it in GitHub Desktop.

Select an option

Save gabrieltheodoropoulos/59dc104163b5718018c6c55309b110fb to your computer and use it in GitHub Desktop.
PressActions modifier - Handle press and release events in SwiftUI
struct PressActions: ViewModifier {
var onPress: () -> Void
var onRelease: () -> Void
func body(content: Content) -> some View {
content
.simultaneousGesture(
DragGesture(minimumDistance: 0)
.onChanged({ _ in
onPress()
})
.onEnded({ _ in
onRelease()
})
)
}
}
extension View {
func pressAction(onPress: @escaping (() -> Void), onRelease: @escaping (() -> Void)) -> some View {
modifier(PressActions(onPress: {
onPress()
}, onRelease: {
onRelease()
}))
}
}
@olilarkin

olilarkin commented Jun 22, 2021

Copy link
Copy Markdown

Thankyou for this. I would like to apply a similar thing to a slider, so that I can trigger a function when the slider is initially touched and when it is released. I tried applying your pressAction to a Slider but it prevents the Slider from moving. Do you know a way around that?

    @State private var isPressed = false
    @State private var gain = 0.0
    var body: some View {
        Slider(value: $gain, in: 0...100)
            .pressAction {
                isPressed = true
            } onRelease: {
                isPressed = false
            }
    }
}

@gabrieltheodoropoulos

Copy link
Copy Markdown
Author

Hi @olilarkin and thanks for your comment.

The PressActions view modifier contains a drag gesture, and that's what actually disables the default slider behavior. I tried to do what you're asking using tap gestures, but that fails too. The same with long press gesture. So I'm not sure if there's an obvious workaround on that purely in SwiftUI. To suggest an idea, you could create a UISlider subclass in UIKit, and override the touchDown and touchUp events. Then bring the slider to SwiftUI with a custom UIViewRepresentable type. This will probably work.

@AdamWhitcroft

Copy link
Copy Markdown

Hey, thanks for sharing this, I just came across it. While implementing this in an app I’m working on, I discovered something interesting. If you put add a haptic event to both onPress and onRelease (attempting to simulate a mechanical keyboard) the onPress haptic will fire repeatedly if you keep your finger pressed and move it slightly.

Are there any amendments you’d make to your code to somehow account for that?

@gabrieltheodoropoulos

Copy link
Copy Markdown
Author

Hi @AdamWhitcroft, thanks for your comment. That's an interesting point, I'll check it out at first chance and will get back hopefully with a solution.

@jesseauciello

Copy link
Copy Markdown

Thanks for this, @gabrieltheodoropoulos. Wondering if you or @AdamWhitcroft ever came up with a solution to his question regarding haptics?

@gabrieltheodoropoulos

Copy link
Copy Markdown
Author

Hi @jesseauciello. As it seems other tasks took priority and I totally neglected this. Sorry for that, I'll try to work on it the soonest.

@MartinAtElitappar

Copy link
Copy Markdown

Hi, thanks for the article "Handle Press And Release Events in SwiftUI". I will try to use ButtonStyle or PrimitiveButtonStyle instead. The configuration.isPressed can be used for checking if the button is pressed or released. /Martin

@NyiYe

NyiYe commented Feb 23, 2023

Copy link
Copy Markdown

how to implement both on tap gesture and pressAction .

@MartinAtElitappar

Copy link
Copy Markdown

Hi @NyiYe , Are you talking about buttons? Can it work for you to make a custom ButtonStyle and use isPressed? You have the action in the button for the tap gesture. I attach an article "Creating Custom Button Styles In SwiftUI" from Gabriel. (You can maybe explain you needs more?) /Martin

@loryhuz

loryhuz commented Oct 8, 2023

Copy link
Copy Markdown

Unfortunately this is cancelling the scroll in a scrollview if you move your finger on the modified view

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment