2017-09-04 43 views
0

我分类为UINavigationController,并创建了一个处理推送和弹出转换的非交互式动画对象。要完成此操作,我如何添加​​来处理下面的自定义流行动画?我有点困惑从哪里去,所以任何帮助将是伟大的,谢谢!如何添加屏幕边缘平移手势识别器来处理此流行动画?

class CustomNavigationController: UINavigationController { 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     delegate = self 
     isNavigationBarHidden = true 

    } 

} 

extension CustomNavigationController: UINavigationControllerDelegate { 

    // noninteractive animator objects 
    func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { 

     switch operation { 

     case .push: 
      return CustomPushAnimator() 

     case .pop: 
      return CustomPopAnimator() 

     default: 
      return nil 

     } 

    } 

    // the interactive animator controller 
    func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? { 

     switch animationController { 

     case is CustomPopAnimator: 
      return CustomInteractiveController() 

     default: 
      return nil 

    } 

} 

// the noninteractive push animator 
class CustomPushAnimator: NSObject, UIViewControllerAnimatedTransitioning { 

    // push transition duration 
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { 

     return 0.2 

    } 

    // push transition animation 
    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { 

     let viewWidth = UIScreen.main.bounds.width 
     let viewHeight = UIScreen.main.bounds.height 
     let containerView = transitionContext.containerView 
     let toViewController = transitionContext.viewController(forKey: .to) 

     containerView.addSubview((toViewController?.view)!) 
     toViewController?.view.frame = CGRect(x: viewWidth, y: 0, width: viewWidth, height: viewHeight) 

     UIView.animate(withDuration: transitionDuration(using: transitionContext), delay: 0, options: UIViewAnimationOptions.curveEaseInOut, animations: { 
      toViewController?.view.frame = CGRect(x: 0, y: 0, width: viewWidth, height: viewHeight) 
     }, completion: { finished in 
      transitionContext.completeTransition(!transitionContext.transitionWasCancelled) 
     }) 

    } 

} 

// the noninteractive pop animator 
class CustomPopAnimator: NSObject, UIViewControllerAnimatedTransitioning { 

    // pop transition duration 
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { 

     return 0.2 

    } 

    // pop transition animation 
    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { 

     let viewWidth = UIScreen.main.bounds.width 
     let viewHeight = UIScreen.main.bounds.height 
     let containerView = transitionContext.containerView 
     let fromViewController = transitionContext.viewController(forKey: .from) 
     let toViewController = transitionContext.viewController(forKey: .to) 

     containerView.insertSubview((toViewController?.view)!, belowSubview: (fromViewController?.view)!) 

     UIView.animate(withDuration: transitionDuration(using: transitionContext), delay: 0, options: UIViewAnimationOptions.curveEaseInOut, animations: { 
      fromViewController?.view.frame = CGRect(x: viewWidth, y: 0, width: viewWidth, height: viewHeight) 
     }, completion: { finished in 
      fromViewController?.view.removeFromSuperview() 
      transitionContext.completeTransition(!transitionContext.transitionWasCancelled) 
     }) 

    } 

} 

class CustomInteractiveController: NSObject, UIViewControllerInteractiveTransitioning { 

    func startInteractiveTransition(_ transitionContext: UIViewControllerContextTransitioning) { 

     // I think the edge screen pan gesture goes here? Again, any advice is greatly appreciated! 

    } 

} 
+1

对于那个低估了这个问题的人,我很感激原因。我花了很多时间研究和编写这段代码,并且提出了一个非常具体的问题,它给了什么? – sconewolf

回答

1

一般情况下,写一个互动的自定义过渡动画的程序是:转变开始

  1. 之前,必须给予负责的过渡委托的视图控制器。

  2. 您将拥有一个跟踪交互式手势的手势识别器。当手势识别器识别时,它触发到新视图控制器的转换。

  3. 随着转换开始,代表将被要求提供动画控制器。您将返回一个UIViewControllerAnimatedTransitioning对象。

  4. 该代表还将被要求提供交互控制器。您将返回一个UIViewControllerInteractiveTransitioning对象(或nil以防止转换为交互式)。该对象实现了startInteractiveTransition(_:)

  5. 手势识别器继续在转换上下文中不断调用updateInteractiveTransition(_:),并管理动画帧。

  6. 手势迟早会结束。此时,我们必须决定是否宣布过渡完成或取消。一种典型的方法是说,如果用户执行了超过一半的完整手势,则构成完成;否则,它构成取消。我们相应地完成动画。

  7. 动画现在已完成,其完成功能被调用。我们必须调用转换上下文的finishInteractiveTransitioncancelInteractiveTransition,然后用一个参数来调用其completeTransition(_:),该参数指出转换是完成还是取消。

  8. 我们的animationEnded被调用,我们清理。

在过去,你可以使用一个UIPercentDrivenInteractiveTransition对象来帮助你,但我总是用我的自定义过渡动画时下UIViewPropertyAnimator(iOS版10及更高版本);你将不得不开始重写你的整个代码来做到这一点。我通常保留三个实例属性:UIViewPropertyAnimator,转换上下文(因为手势识别器需要引用)以及一个Bool标志,表明这是否是交互式动画(因为相同的代码可以重复用于交互式和非交互式版本动画)。

+0

我接受了您的建议,并使用'UIViewPropertyAnimator'重构了动画。我创建了一个Gist https://gist.github.com/sconewolf/7a849fc691b63cf8721d6151831feae8编辑,但无法弄清楚如何将平移手势识别器和处理程序链接到交互控制器(在底部)。缺少的链接是什么?有很多教程使用'UIPercentDrivenInteractiveTransition'(我过去做过但因0.999黑客而感到厌恶),但没有找到使用“UIViewPropertyAnimator”的教程(很明显,因为它到现在为止还没有iOS 10 )。 – sconewolf

+0

如果你知道我是谁,你知道我的书的代码是什么,你可以找到示例代码来演示我在答案中所说的内容。 – matt

相关问题