2017-09-19 17 views
0

如何複製iOS通知中心窗口的彈跳效果,該窗口落到屏幕的底部並在沒有低於窗口高度的情況下彈跳?這似乎使用阻尼和彈簧速度,但是如何防止物體(例如在這種情況下)超過其標記並回彈?如何複製在iOS通知中心窗口中看到的拖放/反彈動畫效果?

+0

可能是https://stackoverflow.com/questions/21892105/how-to-create-a-uiview-bounce-animation和https://stackoverflow.com/questions/24904620/pullable-view-like - 通知中心反彈 – rmaddy

回答

1

最後回答:您可以建立自己的自定義轉換。

假設你有兩個視圖控制器,StartControllerEndController。您希望將此自定義轉換從StartController發生到EndController。

1)像這樣製作自定義過渡對象:

class CustomSlideTransition: NSObject, UIViewControllerAnimatedTransitioning { 

    var duration: Double = 1.0 

    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { 
     return duration 
    } 

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { 

     // Access EndController 

     let toViewController = transitionContext.viewController(forKey: .to) as! EndController 

     // Access the container view : 

     let containerView = transitionContext.containerView 

     // Move EndController's view frame: 

     toViewController.view.frame.origin.y -= UIScreen.main.bounds.size.height 

     containerView.addSubview(toViewController.view) 

     // Adjust the properties of the spring to what fits your needs the most: 

     UIView.animate(withDuration: duration, delay: 0.0, usingSpringWithDamping: 0.2, initialSpringVelocity: 7.0, options: [.curveEaseInOut], animations: { 

      // Get your EndController's view frame moves back to its final position 

      toViewController.view.frame.origin.y += UIScreen.main.bounds.size.height 

     }, completion: { (finished) in 

      transitionContext.completeTransition(!transitionContext.transitionWasCancelled) 
     }) 
    } 
} 

2)在您的StartController的prepareForSegue方法,委託設置爲self

class StartController: UIViewController { 

    // ... 

    // MARK: PrepareForSegue 

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 

     if let destinationController = segue.destination as? EndController { 

      destinationController.transitioningDelegate = self 

     } 

    } 

    // ... 

} 

3 )使StartController符合UIViewControllerTransitioningDelegate

extension StartController: UIViewControllerTransitioningDelegate { 

    // MARK: UIViewControllerTransitioningDelegate 

    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { 
     return CustomSlideTransition() 
    } 

} 

4)不管你想要設計你的EndController!

注意:您可能還想要添加自定義轉換以解除EndController。

更新:現在,如果你真的不想要您的視圖控制器甚至反彈有點出乎窗口,使用spring這裏可能不是最好的一段路要走。 由於在iPhone上使用滑動(從頂部)偏移來計算反彈效果「功率」,因此您可能需要使用關鍵幀動畫定製更多的動畫塊,或者如果您願意,可以使用UIKIT Dynamics

UIView.animate(withDuration: duration, animations: { 

    toViewController.view.frame.origin.y += UIScreen.main.bounds.size.height 

}, completion: { (finished) in 

    // Create a custom bounce effect that doesn't go beyond the window (ie. only negative values) 

    let animation = CAKeyframeAnimation(keyPath: "transform.translation.y") 
    animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) 
    animation.duration = 0.75 
    animation.autoreverses = false 

    // Depending on how you would like to present EndController, you may want to change the hardcoded values below. 
    // For example you could make it so that if the user swipes really fast, it would bounce even more.. 

    animation.values = [0, -60, 0, -25, 0] 

    // Add the key frame animation to the view's layer : 

    toViewController.view.layer.add(animation, forKey: "bounce") 

    transitionContext.completeTransition(!transitionContext.transitionWasCancelled) 
}) 
+0

我認爲問題是關於動畫打開通知中心,它在屏幕底部彈跳。 – nathan

+0

啊,這是有道理的!我會更新我的答案。 – Alex

1

看看UIKitDynamics。這將允許您將物理和碰撞應用到您的視圖。

您可以從屏幕頂部看到一個視圖,並與屏幕底部的視圖相沖突。您需要使用UIGravityBehaviorUICollisionBehavior,並且應該能夠調整常量以獲得所需的效果。

相關問題