如何复制iOS Notification Center窗口中看到的Drop/Bounce动画效果



一个人如何复制iOS通知中心窗口的弹跳效果,该iOS通知中心窗口落在屏幕的底部并弹跳而不从窗口高度以下行驶而弹跳?这似乎使用阻尼和弹簧速度,但是您如何防止对象(在这种情况下)超出其标记并向后缓冲?

查看UIKitDynamics。这将使您能够将物理和碰撞应用于您的观点。

您可以看到从屏幕顶部掉下来的视图,并在屏幕底部的视图碰撞。您需要使用UIGravityBehaviorUICollisionBehavior,并且应该能够调整常数以获得所需的效果。

更新答案:您可以构建自己的自定义过渡。

说您有两个视图控制器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)
})

最新更新