ios – The best way to detect iPad trackpad touch-down (indirectPointer) to instantly cease coasting animation

0
1
ios – The best way to detect iPad trackpad touch-down (indirectPointer) to instantly cease coasting animation


I requested the query on Apple’s developer boards and that is the reply from “Apple Frameworks Engineer”:

There is a false impression right here that’s inflicting you issues. I might advocate this video from WWDC20 beginning right here (however actually simply the entire video):

https://developer.apple.com/movies/play/wwdc2020/10094/?time=146

A pointer-based contact is just going to be UITouch.Section.started -> UITouch.Section.ended when you could have clicked down on the pointing system (there can even be an related buttonMask). When your finger is on the contact floor of the trackpad or Magic Mouse it can not be in these phases, however a section like UITouch.Section.regionEntered or UITouch.Section.regionMoved.

Gestures like UIPanGestureRecognizer, UITapGestureRecognizer, and UILongPressGestureRecognizer don’t eat touches in these phases, in order that’s why they aren’t working for you. And to be clear, there is no such thing as a solution to inform these gestures to take action.

The one gesture that consumes these kind of hovering touches is UIHoverGestureRecognizer. I might advocate including a UIHoverGestureRecognizer to one among your views. Do word that that is going to fireplace at any time when the pointer is seen and inside your view, so if this can be a giant container, that may very well be frequent. You might wish to allow this gesture when the momentum spinning begins, however in any other case maintain it disabled.

Hope that helps!

This did resolve my drawback, nevertheless it turned out that I could not simply activate the hover recognizer instantly after my pan recognizer ended — it could hearth off some residual .modified occasions and trigger the coasting animation to freeze instantly.

So my implementation was to start out looking forward to the touches when my pan recognizer ended, however after a brief delay of 1/tenth of a second. I wrote this scheduleStartWatchingForTrackpadTouches() methodology for my view controller and had the .ended handler for the pan recognizer name it:

func scheduleStartWatchingForTrackpadTouches() {
    DispatchQueue.major.asyncAfter(deadline: .now() + 0.1) { [weak self] in
        self?.startWatchingForTrackpadTouches()
    }
}

Then I used this pair of strategies to create and activate/deactivate the recognizer as wanted:

func startWatchingForTrackpadTouches() {
    // Create the recognizer the primary time by way of
    if hoverRecognizer == nil {
        hoverRecognizer = UIHoverGestureRecognizer(goal: self, motion: #selector(handleHover(_:)))
    }
        
    // Add the recognizer to the view
    if let recognizer = hoverRecognizer {
        view.addGestureRecognizer(recognizer)
    }
}

func stopWatchingForTrackpadTouches() {
    // Take away the recognizer from the view
    if let recognizer = hoverRecognizer {
        view.removeGestureRecognizer(recognizer)
    }
}

Lastly, that is the occasion handler for the recognizer:

@objc non-public func handleHover(_ recognizer: UIHoverGestureRecognizer) {
    if recognizer.state == .modified {
        // Notify of contact start
        touchesBegan()
        
        // Don’t watch till explicitly requested
        stopWatchingForTrackpadTouches()
    }
}

On the primary .modified message I name a technique named touchesBegan() in my opinion controller to freeze the animations, after which I take away the recognizer so it solely fires as soon as and is disabled till it is wanted for the subsequent pan gesture.

LEAVE A REPLY

Please enter your comment!
Please enter your name here