iOS10 中的动画导航栏 barTintColor 更改不起作用
Animate navigation bar barTintColor change in iOS10 not working
我升级到XCode8.0/iOS10,现在我的导航条变色动画没有效果了,直接变色,没有任何动画。
UIView.animateWithDuration(0.2, animations: {
self.navigationController?.navigationBar.barTintColor = currentSection.color!
})
有人知道如何解决这个问题吗?
要在 iOS10 中设置导航栏颜色变化的动画,您需要在动画块中设置颜色后调用 layoutIfNeeded
。
示例代码:
UIView.animateWithDuration(0.5) {
self.navigationController?.navigationBar.barTintColor = UIColor.redColor()
self.navigationController?.navigationBar.layoutIfNeeded()
}
此外,我想告知 Apple doesn’t officialy support 动画在诸如 barTintColor 等属性中,因此该方法可能随时中断。
If you call -layoutIfNeeded on the navigation bar during the animation
block it should update its background properties, but given the nature
of what these properties do, there really hasn't ever been any kind of
guarantee that you could animate any of them.
交互式动画
定义协议:
/// Navigation bar colors for `ColorableNavigationController`, called on `push` & `pop` actions
public protocol NavigationBarColorable: UIViewController {
var navigationTintColor: UIColor? { get }
var navigationBarTintColor: UIColor? { get }
}
public extension NavigationBarColorable {
var navigationTintColor: UIColor? { return nil }
}
定义自定义 NavigationController
子类:
class AppNavigationController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
navigationBar.shadowImage = UIImage()
if let colors = rootViewController as? NavigationBarColorable {
setNavigationBarColors(colors)
}
}
private var previousViewController: UIViewController? {
guard viewControllers.count > 1 else {
return nil
}
return viewControllers[viewControllers.count - 2]
}
override open func pushViewController(_ viewController: UIViewController, animated: Bool) {
if let colors = viewController as? NavigationBarColorable {
setNavigationBarColors(colors)
}
super.pushViewController(viewController, animated: animated)
}
override open func popViewController(animated: Bool) -> UIViewController? {
if let colors = previousViewController as? NavigationBarColorable {
setNavigationBarColors(colors)
}
// Let's start pop action or we can't get transitionCoordinator()
let popViewController = super.popViewController(animated: animated)
// Secure situation if user cancelled transition
transitionCoordinator?.animate(alongsideTransition: nil, completion: { [weak self] context in
guard let `self` = self else { return }
guard let colors = self.topViewController as? NavigationBarColorable else { return }
self.setNavigationBarColors(colors)
})
return popViewController
}
override func popToRootViewController(animated: Bool) -> [UIViewController]? {
if let colors = rootViewController as? NavigationBarColorable {
setNavigationBarColors(colors)
}
let controllers = super.popToRootViewController(animated: animated)
return controllers
}
private func setNavigationBarColors(_ colors: NavigationBarColorable) {
if let tintColor = colors.navigationTintColor {
navigationBar.titleTextAttributes = [
.foregroundColor : tintColor
]
navigationBar.tintColor = tintColor
}
navigationBar.barTintColor = colors.navigationBarTintColor
}
}
现在您可以在 AppNavigationController
内的任何控制器中符合 NavigationBarColorable
并给它任何您想要的颜色。
extension FirstViewController: NavigationBarColorable {
public var navigationBarTintColor: UIColor? { UIColor.red }
public var navigationTintColor: UIColor? { UIColor.white }
}
extension SecondViewController: NavigationBarColorable {
public var navigationBarTintColor: UIColor? { UIColor.blue }
public var navigationTintColor: UIColor? { UIColor.orange }
}
不要忘记实现这个有用的扩展:
extension UINavigationController {
var rootViewController: UIViewController? {
return viewControllers.first
}
}
我升级到XCode8.0/iOS10,现在我的导航条变色动画没有效果了,直接变色,没有任何动画。
UIView.animateWithDuration(0.2, animations: {
self.navigationController?.navigationBar.barTintColor = currentSection.color!
})
有人知道如何解决这个问题吗?
要在 iOS10 中设置导航栏颜色变化的动画,您需要在动画块中设置颜色后调用 layoutIfNeeded
。
示例代码:
UIView.animateWithDuration(0.5) {
self.navigationController?.navigationBar.barTintColor = UIColor.redColor()
self.navigationController?.navigationBar.layoutIfNeeded()
}
此外,我想告知 Apple doesn’t officialy support 动画在诸如 barTintColor 等属性中,因此该方法可能随时中断。
If you call -layoutIfNeeded on the navigation bar during the animation block it should update its background properties, but given the nature of what these properties do, there really hasn't ever been any kind of guarantee that you could animate any of them.
交互式动画
定义协议:
/// Navigation bar colors for `ColorableNavigationController`, called on `push` & `pop` actions
public protocol NavigationBarColorable: UIViewController {
var navigationTintColor: UIColor? { get }
var navigationBarTintColor: UIColor? { get }
}
public extension NavigationBarColorable {
var navigationTintColor: UIColor? { return nil }
}
定义自定义 NavigationController
子类:
class AppNavigationController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
navigationBar.shadowImage = UIImage()
if let colors = rootViewController as? NavigationBarColorable {
setNavigationBarColors(colors)
}
}
private var previousViewController: UIViewController? {
guard viewControllers.count > 1 else {
return nil
}
return viewControllers[viewControllers.count - 2]
}
override open func pushViewController(_ viewController: UIViewController, animated: Bool) {
if let colors = viewController as? NavigationBarColorable {
setNavigationBarColors(colors)
}
super.pushViewController(viewController, animated: animated)
}
override open func popViewController(animated: Bool) -> UIViewController? {
if let colors = previousViewController as? NavigationBarColorable {
setNavigationBarColors(colors)
}
// Let's start pop action or we can't get transitionCoordinator()
let popViewController = super.popViewController(animated: animated)
// Secure situation if user cancelled transition
transitionCoordinator?.animate(alongsideTransition: nil, completion: { [weak self] context in
guard let `self` = self else { return }
guard let colors = self.topViewController as? NavigationBarColorable else { return }
self.setNavigationBarColors(colors)
})
return popViewController
}
override func popToRootViewController(animated: Bool) -> [UIViewController]? {
if let colors = rootViewController as? NavigationBarColorable {
setNavigationBarColors(colors)
}
let controllers = super.popToRootViewController(animated: animated)
return controllers
}
private func setNavigationBarColors(_ colors: NavigationBarColorable) {
if let tintColor = colors.navigationTintColor {
navigationBar.titleTextAttributes = [
.foregroundColor : tintColor
]
navigationBar.tintColor = tintColor
}
navigationBar.barTintColor = colors.navigationBarTintColor
}
}
现在您可以在 AppNavigationController
内的任何控制器中符合 NavigationBarColorable
并给它任何您想要的颜色。
extension FirstViewController: NavigationBarColorable {
public var navigationBarTintColor: UIColor? { UIColor.red }
public var navigationTintColor: UIColor? { UIColor.white }
}
extension SecondViewController: NavigationBarColorable {
public var navigationBarTintColor: UIColor? { UIColor.blue }
public var navigationTintColor: UIColor? { UIColor.orange }
}
不要忘记实现这个有用的扩展:
extension UINavigationController {
var rootViewController: UIViewController? {
return viewControllers.first
}
}