Анимация панели навигации barTintColor изменение в iOS10 не работает
Я обновился до XCode 8.0/iOS 10, и теперь анимация изменения цвета моей навигационной панели больше не работает, она напрямую меняет цвет без анимации.
UIView.animateWithDuration(0.2, animations: {
self.navigationController?.navigationBar.barTintColor = currentSection.color!
})
Кто-нибудь знает, как это исправить?
Ответы
Ответ 1
Для анимации изменения цвета навигации в браузере iOS10 вам нужно вызвать layoutIfNeeded
после установки цвета внутри блока анимации.
Пример кода:
UIView.animateWithDuration(0.5) {
self.navigationController?.navigationBar.barTintColor = UIColor.redColor()
self.navigationController?.navigationBar.layoutIfNeeded()
}
Также я хочу сообщить, что Apple не поддерживает официальную поддержку в таких свойствах, как barTintColor, поэтому способ может прерываться в любое время.
Если вы вызываете -layoutIfNeeded на панели навигации во время анимации блок должен обновить свои фоновые свойства, но с учетом природы из того, что делают эти свойства, действительно никогда не было никаких что вы можете анимировать любой из них.
Ответ 2
Интерактивная анимация
![Interactive animation]()
Определите протокол:
/// 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 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
}
}
Теперь вы можете соответствовать NavigationBarColorable
в любом контроллере внутри AppNavigationController
и назначать ему любой цвет, который хотите.
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
}
}