Interactive transition is not linear

I play with a custom and interactive view controller transistor with UIPercentDrivenInteractiveTransition . I am creating an application that represents a map (another controller). I made custom transistors with UIViewControllerAnimatedTransitioning , which animates the map display controller in the same way as the presentation style of the standard model.

 func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { {...} let fullScreenFrame = transitionContext.finalFrame(for: cardVC) let offsetFrame = cardVC.view.frame.offsetBy(dx: 0, dy: cardVC.view.frame.height) let finalFrame = presenting ? fullScreenFrame : offsetFrame cardVC.view.frame = presenting ? offsetFrame : fullScreenFrame containerView.addSubview(cardVC.view) UIView.animateKeyframes( withDuration: transitionDuration(using: transitionContext), delay: 0, options: UIViewKeyframeAnimationOptions.calculationModeLinear, animations: { UIView.addKeyframe( withRelativeStartTime: 0, relativeDuration: 1, animations: { [weak self] in guard let strongSelf = self else { return } backgroundView.alpha = strongSelf.presenting ? 1 : 0 }) UIView.addKeyframe( withRelativeStartTime: 0, relativeDuration: 1, animations: { cardVC.view.frame = finalFrame }) }, completion: { finished in backgroundView.removeFromSuperview() gradientView.alpha = 1 transitionContext.completeTransition(!transitionContext.transitionWasCancelled) }) } 

And then I use the gesture recognizer to interactively control the firing animation:

 func handleGesture(_ gestureRecognizer: UIScreenEdgePanGestureRecognizer) { let translation = gestureRecognizer.translation(in: gestureRecognizer.view) var progress = (translation.y / (UIScreen.main.bounds.height - 70)) progress = CGFloat(fminf(fmaxf(Float(progress), 0.0), 1.0)) switch gestureRecognizer.state { case .began: interactionInProgress = true viewController.dismiss(animated: true, completion: nil) case .changed: shouldCompleteTransition = progress > 0.35 update(progress) case .cancelled: interactionInProgress = false cancel() case .ended: interactionInProgress = false if !shouldCompleteTransition { cancel() } else { finish() } default: print("Unsupported") } } 

When I reject the presented view controller by dragging it, it doesn't seem to move linearly with a gesture. It seems that the Interaction Controller uses some easeInEaseOut function. Perhaps set UIPercentDrivenInteractiveTransition timingCurve to make the transition linear. Is this possible, or am I getting something wrong?

+6
source share
3 answers

I had the same problem, I was able to set my own animation curve for animateKeyframes using UIView.setAnimationCurve , like so:

 UIView.animateKeyframes(withDuration: 4, delay: 0, options: [], animations: { UIView.setAnimationCurve(.linear) UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.24, animations: { // Animations... }) // Other key frames... }) 
+1
source

You yourself provided the default animations to ease the extraction of the time curve without setting the time curve to anything else in your call to UIView.animateKeyframes . This applies even during interaction.

Please note that setting the animation options to UIViewKeyframeAnimationOptions.calculationModeLinear does not change the time curve (in case you think you are doing here). The way to add a linear time curve to a keyframe animation with linear calculation is as follows:

 var opts : UIViewKeyframeAnimationOptions = .calculationModeLinear let opt2 : UIViewAnimationOptions = .curveLinear opts.insert(UIViewKeyframeAnimationOptions(rawValue:opt2.rawValue)) // and now use `opts` as your `options` 
0
source

In my case, it works with interruptibleAnimator(using:) by returning UIViewPropertyAnimator

0
source

Source: https://habr.com/ru/post/1270795/


All Articles