自定义 UINavigationController 动画
Custom UINavigationController animation
我正在尝试实现自定义过渡动画,这就是我所拥有的
class NavDelegate: NSObject, UINavigationControllerDelegate {
private let animator = Animator()
func navigationController(_ navigationController: UINavigationController,
animationControllerFor operation: UINavigationControllerOperation,
from fromVC: UIViewController,
to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return animator
}
}
class Animator: NSObject, UIViewControllerAnimatedTransitioning {
func transitionDuration(using context: UIViewControllerContextTransitioning?) -> TimeInterval {
return 10.0
}
func animateTransition(using context: UIViewControllerContextTransitioning) {
let fromViewController = context.viewController(forKey: UITransitionContextViewControllerKey.from)!
let toViewController = context.viewController(forKey: UITransitionContextViewControllerKey.to)!
if fromViewController is ViewController {
self.pushAnimation(from: fromViewController as! ViewController,
to: toViewController as! VC2ViewController,
with: context)
}
if toViewController is ViewController {
print("pop")
}
}
func pushAnimation(from viewController: ViewController,
to destinationViewController: VC2ViewController,
with context: UIViewControllerContextTransitioning) {
context.containerView.addSubview(destinationViewController.view)
//block 1
for cell in viewController.tableView1.visibleCells {
if let castCell = cell as? VC1TableViewCell {
castCell.contentViewToLeft.constant = -UIScreen.main.bounds.width
castCell.contentViewToRight.constant = UIScreen.main.bounds.width
let duration = Double(viewController.tableView1.visibleCells.index(of: cell)!)/Double(viewController.tableView1.visibleCells.count) + 0.2
UIView.animate(withDuration: duration, animations: {
castCell.layoutIfNeeded()
}) { animated in
}
}
}
//block 2
for cell in destinationViewController.tableView2.visibleCells {
if let castCell = cell as? VC2TableViewCell {
castCell.contentViewToLeft.constant = -UIScreen.main.bounds.width
castCell.contentViewToRight.constant = UIScreen.main.bounds.width
let duration = Double(destinationViewController.tableView2.visibleCells.index(of: cell)!)/Double(destinationViewController.tableView2.visibleCells.count) + 0.2
UIView.animate(withDuration: duration, animations: {
castCell.layoutIfNeeded()
}) { animated in
if duration > 1.1 {
context.completeTransition(!context.transitionWasCancelled)
}
}
}
}
}
}
问题是目标控制器(块 2)的约束动画从不动画,layoutIfNeeded()
执行时没有动画,尽管块 1 正在运行。可能是什么问题?
我花了几天时间测试
transitionDuration(using context: UIViewControllerContextTransitioning?)
函数,发现都是在DispatchQueue.main.async {}
里面调用一些toViewController
动画块。不确定它是如何工作的,但我已经让我的代码按照我的计划工作。
我正在尝试实现自定义过渡动画,这就是我所拥有的
class NavDelegate: NSObject, UINavigationControllerDelegate {
private let animator = Animator()
func navigationController(_ navigationController: UINavigationController,
animationControllerFor operation: UINavigationControllerOperation,
from fromVC: UIViewController,
to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return animator
}
}
class Animator: NSObject, UIViewControllerAnimatedTransitioning {
func transitionDuration(using context: UIViewControllerContextTransitioning?) -> TimeInterval {
return 10.0
}
func animateTransition(using context: UIViewControllerContextTransitioning) {
let fromViewController = context.viewController(forKey: UITransitionContextViewControllerKey.from)!
let toViewController = context.viewController(forKey: UITransitionContextViewControllerKey.to)!
if fromViewController is ViewController {
self.pushAnimation(from: fromViewController as! ViewController,
to: toViewController as! VC2ViewController,
with: context)
}
if toViewController is ViewController {
print("pop")
}
}
func pushAnimation(from viewController: ViewController,
to destinationViewController: VC2ViewController,
with context: UIViewControllerContextTransitioning) {
context.containerView.addSubview(destinationViewController.view)
//block 1
for cell in viewController.tableView1.visibleCells {
if let castCell = cell as? VC1TableViewCell {
castCell.contentViewToLeft.constant = -UIScreen.main.bounds.width
castCell.contentViewToRight.constant = UIScreen.main.bounds.width
let duration = Double(viewController.tableView1.visibleCells.index(of: cell)!)/Double(viewController.tableView1.visibleCells.count) + 0.2
UIView.animate(withDuration: duration, animations: {
castCell.layoutIfNeeded()
}) { animated in
}
}
}
//block 2
for cell in destinationViewController.tableView2.visibleCells {
if let castCell = cell as? VC2TableViewCell {
castCell.contentViewToLeft.constant = -UIScreen.main.bounds.width
castCell.contentViewToRight.constant = UIScreen.main.bounds.width
let duration = Double(destinationViewController.tableView2.visibleCells.index(of: cell)!)/Double(destinationViewController.tableView2.visibleCells.count) + 0.2
UIView.animate(withDuration: duration, animations: {
castCell.layoutIfNeeded()
}) { animated in
if duration > 1.1 {
context.completeTransition(!context.transitionWasCancelled)
}
}
}
}
}
}
问题是目标控制器(块 2)的约束动画从不动画,layoutIfNeeded()
执行时没有动画,尽管块 1 正在运行。可能是什么问题?
我花了几天时间测试
transitionDuration(using context: UIViewControllerContextTransitioning?)
函数,发现都是在DispatchQueue.main.async {}
里面调用一些toViewController
动画块。不确定它是如何工作的,但我已经让我的代码按照我的计划工作。