我正在处理的应用在推送新视图控制器时会更改其导航栏的barTintColor
。现在我们在目标视图控制器的viewWillAppear:
方法中设置了这种颜色,但是我们遇到了一些问题。
按照我们现在这样做的方式,导航栏的颜色会突然变化,而其余的条形内容会像往常一样动画。我喜欢的是酒吧在源颜色和目标颜色之间淡入淡出。有没有办法用公共Cocoa Touch API实现这一目标?
答案 0 :(得分:17)
您可以使用UIViewControllerTransitionCoordinator添加与视图控制器转换的时序和动画曲线相匹配的额外动画。
在视图控制器的动画开始之后,视图控制器的transitionCoordinator
将被设置为(因此在所呈现的视图控制器的viewWillAppear
中)。在转换协调器上使用animateAlongsideTransition:completion:
添加任何额外的动画。
一个例子:
[[self transitionCoordinator] animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
self.navigationController.navigationBar.translucent = NO;
self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
self.navigationController.navigationBar.barTintColor = [UIColor redColor];
} completion:nil];
答案 1 :(得分:1)
为了在推送和弹出期间获得平滑的动画,我必须使导航栏透明,并在其背后为我自己的背景颜色视图设置动画。
import Foundation
import UIKit
class ColorTransitionNavigationController: UINavigationController {
var navigationBarBackgroundView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// Put a background view behind the navigation bar
navigationBarBackgroundView = UIView()
view.insertSubview(navigationBarBackgroundView, belowSubview: navigationBar)
// Make the navigation bar transparent
navigationBar.isTranslucent = true
navigationBar.setBackgroundImage(UIImage(), for: .default)
// Size the colored background to match the navigation bar
navigationBarBackgroundView.translatesAutoresizingMaskIntoConstraints = false
navigationBarBackgroundView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
navigationBarBackgroundView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
navigationBarBackgroundView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
// I used a hard-coded 64 instead of constraining to the height of the navigation bar because
// when calling navigationController.setNavigationBarHidden(true), the height of the navigation bar becomes 0
navigationBarBackgroundView.heightAnchor.constraint(equalToConstant: 64.0).isActive = true
}
func setBarTintColor(color: UIColor, animated: Bool, transitionCoordinator: UIViewControllerTransitionCoordinator?) {
guard let transitionCoordinator = transitionCoordinator, animated else {
navigationBarBackgroundView.backgroundColor = color
return
}
transitionCoordinator.animateAlongsideTransition(in: view, animation: { [weak self] (context) in
let transition = CATransition()
transition.duration = context.transitionDuration
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
self?.navigationBarBackgroundView.layer.add(transition, forKey: nil)
self?.navigationBarBackgroundView.backgroundColor = color
}, completion:nil)
}
}
如果您希望UIViewController在导航栏颜色显示时为其设置动画,请覆盖viewWillAppear
并调用setBarTintColor
。
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
guard let navigationController = navigationController as? ColorTransitionNavigationController else { return }
navigationController.setBarTintColor(color: UIColor.green, animated: animated, transitionCoordinator: transitionCoordinator)
}
答案 2 :(得分:1)
这是一个更简单的修复。当您尝试在barTintColor
中设置导航栏外观时,viewWillDisappear
无法正确设置弹出动画的问题。修复方法是将其设置为willMove(toParentViewController:)
。
以下代码将在推送和弹出期间产生平滑的淡入淡出过渡,无论是通过手势还是按钮按钮启动。在iOS 10和11上测试。
这也适用于动画barStyle
。
import UIKit
class RedViewController: UIViewController {
override func viewWillAppear(_ animated: Bool) {
self.title = "Red"
self.navigationController?.navigationBar.barTintColor = .red
self.navigationController?.navigationBar.tintColor = .white
}
override func willMove(toParentViewController parent: UIViewController?) {
self.navigationController?.navigationBar.barTintColor = .white
self.navigationController?.navigationBar.tintColor = nil
}
}