如何使自定义转换表现得像重力下降?

时间:2014-07-11 23:27:16

标签: ios swift uikit-dynamics custom-transition

效果可以像animateTransition方法中的以下代码一样实现:

UIView.animateWithDuration(duration, 
  delay: 0, 
  usingSpringWithDamping: 0.3, 
  initialSpringVelocity: 0.0, 
  options: .CurveLinear, 
  animations: {
    fromVC.view.alpha = 0.5
    toVC.view.frame = finalFrame
  }, 
  completion: {_ -> () in
    fromVC.view.alpha = 1.0
    transitionContext.completeTransition(true)
  })

但是如何使用重力和碰撞行为(UIGravityBehaviorUICollisionBehavior)来实现它?

更一般的问题可能是“如何使用UIDynamicAnimator自定义UIViewControllers之间的转换?”

1 个答案:

答案 0 :(得分:4)

您可以通过 Custom view controller transitions with UIDynamic behaviors 在帖子 dasdom 下找到解决方案。

Swift代码:

func transitionDuration(transitionContext: UIViewControllerContextTransitioning!) -> NSTimeInterval {
  return 1.0
}

func animateTransition(transitionContext: UIViewControllerContextTransitioning!) {

  // 1. Prepare for the required components
  let toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)
  let finalFrame = transitionContext.finalFrameForViewController(toVC)
  let containerView = transitionContext.containerView()
  let screenBounds = UIScreen.mainScreen().bounds

  // 2. Make toVC at the top of the screen
  toVC.view.frame = CGRectOffset(finalFrame, 0, -1.0 * CGRectGetHeight(screenBounds))
  containerView.addSubview(toVC.view)

  // 3. Set the dynamic animators used by the view controller presentation
  var animator: UIDynamicAnimator? = UIDynamicAnimator(referenceView: containerView)
  let gravity = UIGravityBehavior(items: [toVC.view])
  gravity.magnitude = 10

  let collision = UICollisionBehavior(items: [toVC.view])
  collision.addBoundaryWithIdentifier("GravityBoundary",
    fromPoint: CGPoint(x: 0, y: screenBounds.height),
    toPoint: CGPoint(x: screenBounds.width, y: screenBounds.height))

  let animatorItem = UIDynamicItemBehavior(items: [toVC.view])
  animatorItem.elasticity = 0.5

  animator!.addBehavior(gravity)
  animator!.addBehavior(collision)
  animator!.addBehavior(animatorItem)

  // 4. Complete the transition after the time of the duration
  let nsecs = transitionDuration(transitionContext) * Double(NSEC_PER_SEC)
  let delay = dispatch_time(DISPATCH_TIME_NOW, Int64(nsecs))

  dispatch_after(delay, dispatch_get_main_queue()) {
    animator = nil
    transitionContext.completeTransition(true)
  }
}

比使用animateWithDuration:delay:usingSpringWithDamping:initialSpringVelocity:options:animations:completion:方法稍微复杂一点。

编辑:修正了'transitionDuration'为≤1

时的错误