2017-08-11 4 views
4

Je suis en train de jouer avec une transistion de contrôleur de vue personnalisée et interactive, avec UIPercentDrivenInteractiveTransition. Je construis une application qui présente une carte (autre contrôleur de vue) modalement. J'ai fait des transitions personnalisées avec UIViewControllerAnimatedTransitioning qui anime le contrôleur de vue de carte beaucoup comme le style de présentation de modèle standart.Transition interactive non linéaire

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) 
    }) 
} 

Et puis-je utiliser une reconnaissance pan geste de conduire de manière interactive la rejeter 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") 
     } 
    } 

Lorsque je rejette le contrôleur de vue présenté en le faisant glisser vers le bas, il ne semble pas se déplacer de façon linéaire avec le geste. Il semble que le contrôleur d'interaction utilise une fonction easeInEaseOut. Peut-être régler UIPercentDrivenInteractiveTransitiontimingCurve pour que la transition se déroule linéairement. Est-ce que c'est possible ou est-ce que je me trompe?

Répondre

0

Vous avez vous-même donné à l'animation une courbe de temporisation par défaut pour la décélération, en ne définissant pas la courbe de temporisation sur UIView.animateKeyframes. Cela s'applique même pendant l'interaction.

Notez que la mise en options-UIViewKeyframeAnimationOptions.calculationModeLinear de l'animation ne pas changement de la courbe de synchronisation (dans le cas où ce que vous pensiez que vous accomplissez ici). La manière d'ajouter une courbe de synchronisation linéaire à une animation d'image clé en mode de calcul linéaire est la suivante: