【问题标题】:Animate navigation bar barTintColor change in iOS10 not workingiOS10中的动画导航栏barTintColor更改不起作用
【发布时间】:2016-09-15 15:47:54
【问题描述】:

我升级到XCode 8.0 / iOS 10,现在我的导航栏的颜色变化动画不再起作用了,它直接改变颜色,没有任何动画。

UIView.animateWithDuration(0.2, animations: {
    self.navigationController?.navigationBar.barTintColor = currentSection.color!
})

有人知道如何解决这个问题吗?

【问题讨论】:

    标签: ios swift2 ios10


    【解决方案1】:

    要在iOS10中为导航栏的颜色变化设置动画,你需要在动画块内设置颜色后调用layoutIfNeeded

    示例代码:

    UIView.animateWithDuration(0.5) { 
        self.navigationController?.navigationBar.barTintColor = UIColor.redColor()
        self.navigationController?.navigationBar.layoutIfNeeded()
    }
    

    我还想通知 Apple doesn’t officialy support 动画在 barTintColor 等属性中,以便该方法可以随时中断。

    如果在动画过程中在导航栏上调用 -layoutIfNeeded 块它应该更新其背景属性,但鉴于性质 这些属性的作用,真的从来没有任何一种 保证您可以为其中任何一个设置动画。

    【讨论】:

    • 确实有效,但我的导航栏标题也是动画的(我没有在“animateWithDuration”函数中设置标题。标题从左上角移动到导航中心颜色变化动画时的栏...
    • @Tiois,我认为问题只存在于您的项目中。可能您在同一布局周期中设置标题,请检查您在 ViewController 中更改的所有属性。我已经创建了测试项目并且标题保持不变,你可以在这里查看:dl.dropboxusercontent.com/u/42855950/test.zip
    • 你是对的,设置标题后,我现在在导航上调用 layoutIfNeeded() ,然后使用 layoutIfNeeded() 调用 UIView.animateWithDuration 函数,它工作正常!谢谢。
    • 你拯救了我的一天
    • layoutIfNeeded() 效果惊人,感谢您拯救了这一天。 :)
    【解决方案2】:

    互动动画

    定义一个协议:

    /// 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
        }
    }
    

    【讨论】:

    • 有史以来最好的答案!谢谢。
    猜你喜欢
    • 2020-08-09
    • 1970-01-01
    • 1970-01-01
    • 2021-09-15
    • 2017-02-11
    • 2019-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多