【问题标题】:How do I transition/animate color of UINavigationBar?如何转换/动画 UINavigationBar 的颜色?
【发布时间】:2017-08-18 06:57:39
【问题描述】:

我一直在寻找如何转换/动画UINavigationBarbarTintColor 一段时间,但我只看到不同的答案。有些使用UIView.animateWithDuration,有些使用CATransition,但最有趣的,比如this one 使用animate(alongsideTransition animation..,我喜欢它的声音,但我无法让它正常工作。我是不是做错了什么?

许多人指定我可以在viewWillAppear: 中简单地使用transitionCoordinator。我已经建立了一个新的超级小项目,如下所示:

class RootViewController:UIViewController{ //Only subclassed
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        transitionCoordinator?.animate(alongsideTransition: { [weak self](context) in
            self?.setNavigationColors()
            }, completion: nil)
    }
    func setNavigationColors(){
        //Override in subclasses
    }
}

class FirstViewController: RootViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        self.title = "First"
    }
    override func setNavigationColors(){
        navigationController?.navigationBar.barTintColor = UIColor.white
        navigationController?.navigationBar.tintColor = UIColor.black
        navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.black]
        navigationController?.navigationBar.barStyle = UIBarStyle.default
    }
}
class SecondViewController: RootViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        self.title = "Second"
    }
    override func setNavigationColors(){
        navigationController?.navigationBar.barTintColor = UIColor.black
        navigationController?.navigationBar.tintColor = UIColor.white
        navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
        navigationController?.navigationBar.barStyle = UIBarStyle.black
    }
}

使用此代码,会发生以下情况:

  • FirstSecond 的推送转换看起来很完美。所有元素都完美过渡,可能除了状态栏,它会立即变为白色。我更想知道如何转换它,但我现在会接受它。
  • SecondFirst 的pop-transition 是完全错误的。它会保留 Second 的颜色,直到过渡完成。
  • SecondFirst 的拖动过渡看起来不错,当一直拖动时。同样,当我开始拖动时,状态栏会立即变黑,但我不知道这是否可以解决。
  • SecondFirst 的拖动转换但取消了中间拖动并返回到Second 完全搞砸了。在Second 完全恢复控制之前它看起来很好,然后它突然将自身变为First-colors。这不应该发生。

我对我的RootViewController 做了一些更改,让它变得更好一些。我完全删除了viewWillAppear:,并用这个进行了更改:

class RootViewController:UIViewController{

    override func willMove(toParentViewController parent: UIViewController?) {
        if let last = self.navigationController?.viewControllers.last as? RootViewController{
            if last == self && self.navigationController!.viewControllers.count > 1{
                if let parent = self.navigationController!.viewControllers[self.navigationController!.viewControllers.count - 2] as? RootViewController{
                    parent.setNavigationColors()
                }
            }
        }
    }
    override func viewWillDisappear(_ animated: Bool) {
        if let parent = navigationController?.viewControllers.last as? RootViewController{
            parent.animateNavigationColors()
        }
    }
    override func viewDidAppear(_ animated: Bool) {
        self.setNavigationColors()
    }

    func animateNavigationColors(){
        transitionCoordinator?.animate(alongsideTransition: { [weak self](context) in
            self?.setNavigationColors()
            }, completion: nil)
    }
    func setNavigationColors(){
        //Override in subclasses
    }
}

有了这个更新的代码,我得到了这个:

一些观察:

  • FirstSecond 的转换是一样的
  • SecondFirst 的pop-transition 现在可以正确动画了,除了后退箭头、后退文本(和状态栏,但是是的..)。这些立即变为黑色。在第一个 gif 中,您可以看到后退箭头和后退文本也发生了过渡。
  • SecondFirst的拖动过渡也有这个问题,启动时后退箭头和后退文字突然瞬间变黑。 barTint 已修复,因此在取消拖动时不会出现错误的颜色。

我做错了什么?我该怎么做?

我想要的是平滑过渡所有元素。后退按钮、后退文本、标题、barTint 和状态栏的色调。这不可能吗?

【问题讨论】:

标签: ios uiview uiviewcontroller


【解决方案1】:

在 10 iOS 中它工作不完美:(

将您的导航控制器子类化以使用可见视图控制器的状态栏样式:

class MyNavigationController: UINavigationController {
    override var preferredStatusBarStyle: UIStatusBarStyle {
        return visibleViewController!.preferredStatusBarStyle
    }
}

覆盖Root控制器中的preferredStatusBarStyle并添加设置样式的功能之前弹出动画:

private var _preferredStyle = UIStatusBarStyle.default;
override var preferredStatusBarStyle: UIStatusBarStyle {
    get {
        return _preferredStyle
    }
    set {
        _preferredStyle = newValue
        self.setNeedsStatusBarAppearanceUpdate()
    }

}


func animateNavigationColors(){
        self.setBeforePopNavigationColors()
        transitionCoordinator?.animate(alongsideTransition: { [weak self](context) in
            self?.setNavigationColors()
            }, completion: nil)
    }

func setBeforePopNavigationColors() {
    //Override in subclasses
}

在第一个控制器中:

override func setBeforePopNavigationColors() {
    navigationController?.navigationBar.tintColor = UIColor.white
    navigationController?.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
    self.preferredStatusBarStyle = UIStatusBarStyle.lightContent
}

override func setNavigationColors(){
    navigationController?.navigationBar.barTintColor = UIColor.white
    navigationController?.navigationBar.tintColor = UIColor.black
    navigationController?.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.black]
    navigationController?.navigationBar.barStyle = UIBarStyle.default
    self.preferredStatusBarStyle = UIStatusBarStyle.default
}

第二次:

  override func setNavigationColors(){
        navigationController?.navigationBar.barTintColor = UIColor.black
        navigationController?.navigationBar.tintColor = UIColor.white
        navigationController?.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
        navigationController?.navigationBar.barStyle = UIBarStyle.black
        self.preferredStatusBarStyle = UIStatusBarStyle.lightContent
    }

示例项目:https://github.com/josshad/TestNavBarTransition

【讨论】:

  • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果将来删除其他问题/答案,则仅链接的答案可能会失效。
【解决方案2】:

您可以覆盖UINavigationController 的push 和pop 方法来设置条形颜色。我已将与视图控制器对应的条形颜色存储在其导航项中,其自定义子类为UINavigationItem。以下代码适用于 iOS 11 中的完整过渡和交互式过渡:

import UIKit

class NavigationItem: UINavigationItem {
    @IBInspectable public var barTintColor: UIColor?
}

class NavigationController: UINavigationController, UIGestureRecognizerDelegate {
    func applyTint(_ navigationItem: UINavigationItem?) {
        if let item = navigationItem as? NavigationItem {
            self.navigationBar.barTintColor = item.barTintColor
        }
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        applyTint(self.topViewController?.navigationItem)
        self.interactivePopGestureRecognizer?.delegate = self
    }
    override func pushViewController(_ viewController: UIViewController, animated: Bool) {
        applyTint(viewController.navigationItem)
        super.pushViewController(viewController, animated: animated)
    }

    override func popViewController(animated: Bool) -> UIViewController? {
        let viewController = super.popViewController(animated: animated)

        applyTint(self.topViewController?.navigationItem)
        return viewController
    }

    override func popToViewController(_ viewController: UIViewController, animated: Bool) -> [UIViewController]? {
        let result = super.popToViewController(viewController, animated: animated)

        applyTint(viewController.navigationItem)
        return result
    }

    override func popToRootViewController(animated: Bool) -> [UIViewController]? {
        let result = super.popToRootViewController(animated: animated)

        applyTint(self.topViewController?.navigationItem)
        return result
    }

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return (otherGestureRecognizer is UIScreenEdgePanGestureRecognizer)
    }
}

注意:颜色动画的协调由导航控制器完成

【讨论】:

  • 这个处理标题和状态栏的颜色吗?
  • 两者都对我有用,但你应该自己尝试一下。
  • 我已经对此进行了测试,但它似乎没有涵盖当您使用交互式弹出手势向后滑动然后改变主意并取消手势时的情况 - 在这种情况下它设置视图控制器的色调颜色,如果您没有取消手势,则会弹出该颜色
猜你喜欢
  • 2011-06-29
  • 1970-01-01
  • 1970-01-01
  • 2011-08-04
  • 1970-01-01
  • 1970-01-01
  • 2015-08-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多