[英]Custom segue transition animation
I'm working on an app that utilizes the navigation controller. 我正在开发一个使用导航控制器的应用程序。 I have a certain view controller that has a left and right button in the navigation bar and each button segues to a different view controller.
我有一个特定的视图控制器,在导航栏中有一个左右按钮,每个按钮都连接到另一个视图控制器。 When I press the right button, I just call
self.performSegue(withIdentifier: "ToDestination", sender: nil)
and when I pop back I call _ = self.navigationController?.popViewController(animated: true)
. 当我按下右键时,我只调用
self.performSegue(withIdentifier: "ToDestination", sender: nil)
,当我弹出时,我调用_ = self.navigationController?.popViewController(animated: true)
。
My issue is when I press the left button. 我的问题是按下左按钮时。 I can push and pop, but I want the transition to work opposite of the right button.
我可以按下并弹出,但是我希望过渡与右键相反。 Since I'm pressing the left button, I want the segue to transition from left to right, and when I pop, I want the segue to transition from right to left.
因为按下了左按钮,所以我希望segue从左向右过渡,而当我弹出时,我希望segue从右向左过渡。
I can get the transitions to work the way I want by doing: 通过执行以下操作,我可以按照我想要的方式进行过渡:
//push
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "SearchController") as! SearchController
let transition: CATransition = CATransition()
let timeFunc : CAMediaTimingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.duration = 0.5
transition.timingFunction = timeFunc
transition.type = kCATransitionPush
transition.subtype = kCATransitionFromLeft
self.navigationController!.view.layer.add(transition, forKey: kCATransition)
self.navigationController!.pushViewController(vc, animated: true)
//pop
let transition: CATransition = CATransition()
let timeFunc : CAMediaTimingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.duration = 0.5
transition.timingFunction = timeFunc
transition.type = kCATransitionPush
transition.subtype = kCATransitionFromRight
self.navigationController!.view.layer.add(transition, forKey: kCATransition)
_ = self.navigationController?.popViewController(animated: true)
This works, but there is a black flash when transitioning between view controllers. 这可行,但是在视图控制器之间转换时会出现黑色闪烁。 Is there a better way to get the default transition animation?
有没有更好的方法来获取默认的过渡动画?
The best way to achieve that is to create custom push and pop animation by conforming UIViewControllerAnimatedTransitioning
protocol:- 最好的实现方法是通过遵循
UIViewControllerAnimatedTransitioning
协议来创建自定义的推送和弹出动画:
//CustomPushAnimation class
import UIKit
class CustomPushAnimation: NSObject, UIViewControllerAnimatedTransitioning {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.2
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let containerVw = transitionContext.containerView
let fromViewController = transitionContext.viewController(forKey: .from)
let toViewController = transitionContext.viewController(forKey: .to)
guard let fromVc = fromViewController, let toVc = toViewController else { return }
let finalFrame = transitionContext.finalFrame(for: toVc)
//Below line will start from left
toVc.view.frame = finalFrame.offsetBy(dx: -finalFrame.size.width/2, dy: 0)
containerVw.addSubview(toVc.view)
UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: {
toVc.view.frame = finalFrame
fromVc.view.alpha = 0.5
}, completion: {(finished) in
transitionContext.completeTransition(finished)
fromVc.view.alpha = 1.0
})
}
}
//CustomPopAnimation class
import UIKit
class CustomPopAnimation: NSObject, UIViewControllerAnimatedTransitioning {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.2
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let containerView = transitionContext.containerView
let fromViewController = transitionContext.viewController(forKey: .from)
let toViewController = transitionContext.viewController(forKey: .to)
guard let fromVc = fromViewController,
let toVc = toViewController,
let snapshotView = fromVc.view.snapshotView(afterScreenUpdates: false)
else { return }
let finalFrame = transitionContext.finalFrame(for: fromVc)
toVc.view.frame = finalFrame
containerView.addSubview(toVc.view)
containerView.sendSubview(toBack: toVc.view)
snapshotView.frame = fromVc.view.frame
containerView.addSubview(snapshotView)
fromVc.view.removeFromSuperview()
UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: {
//Below line will start from right
snapshotView.frame = finalFrame.offsetBy(dx: -finalFrame.size.width, dy: 0)
}, completion: {(finished) in
snapshotView.removeFromSuperview()
transitionContext.completeTransition(finished)
})
}
}
And last you need to present the new View controller with setting animation flag to true otherwise it will not work
最后,您需要展示新的View控制器,并将animation flag设置为true,否则它将无法正常工作
//Below code should be inside YourViewController
let vc = UIStoryboard(name: "storyboardName", bundle: nil).instantiateViewController(withIdentifier: "ViewControllerIdentifier") let navigationController = BaseNavigationController(rootViewController: vc)
navigationController.transitioningDelegate = self
present(navigationController, animated: true, completion: nil)
You also need to conform UIViewControllerTransitioningDelegate protocol in order to work animation
您还需要遵循UIViewControllerTransitioningDelegate协议才能制作动画
extension YourViewController: UIViewControllerTransitioningDelegate {
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return customPushAnimation
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return customPopAnimation
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.