UINavigationBar不同颜色的丝滑过度

之前在QQ的app中发现他的用户主页的NavigationBar是透明的而且与上一个有颜色的NavigationBar的过度非常丝滑

当时一直不知道这个效果怎么实现,研究了ViewController的API才发现,其实这个功能可以根据apple自己的api实现,而不需要自己封装动画效果

实现效果看下面的动画

探究

在仔细阅读ViewController的API的时候,发现UIViewControllerTransitionCoordinator这个类没怎么用过,看apple doc发现好像和转场动画有关系
An object that adopts the UIViewControllerTransitionCoordinator protocol provides support for animations associated with a view controller transition.
这个协议中有个UIViewController的Category

1
@interface UIViewController(UIViewControllerTransitionCoordinator)
- (id <UIViewControllerTransitionCoordinator>)transitionCoordinator NS_AVAILABLE_IOS(7_0);
@end

apple doc是这样解释的

When a presentation or dismissal is in progress, this method returns the transition coordinator object associated with that transition. If there is no in-progress transition associated with the current view controller, UIKit checks the view controller’s ancestors for a coordinator object and returns that object if it exists. You can use this object to create additional animations and synchronize them with the transition animations.

Container view controllers can override this method but in most cases should not need to. If you do override this method, first check to see if there is an appropriate transition coordinator to return, and, if there is, return it. If there is no appropriate coordinator to return, call super.

我的翻译功底不是太好,怕翻译错就不翻译了,主要还是看第一段的最后一句话,基本上就是说你可以利用这个object在viewController做专场动画的时候,添加一些自己的动画效果这些动画可以转场动画实现同步。之前我们做些转场动画的时候都需要在UINavigationControllerDelegate中去自定义UIViewControllerAnimatedTransitioning。

实现

看到这里我有些兴奋,应该彻底搞清楚UIViewControllerTransitionCoordinator这个协议了。
接下来我们慢慢来解读它,首先看framework中的头文件中的函数

1
- animateAlongsideTransition:completion:

依旧看apple doc对这个函数的解释

Runs the specified animations at the same time as the view controller transition animations.

看到这里我想我们可以马上能解决我们上面不同颜色NavigationBar的顺滑切换了。基本思路是这样的,在两个不同颜色的NavigationBar的ViewController中实现下面的代码

1
- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
      
    [[self transitionCoordinator] animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
        self.navigationController.navigationBar.translucent = NO;
        self.navigationController.navigationBar.barStyle = UIBarStyleDefault;
        
        // text color
        [self.navigationController.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]}];
        
        // navigation items and bar button items color
        self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
        
        // background color
        self.navigationController.navigationBar.barTintColor = [UIColor redColor];
    } completion:nil];   
 }

当然你需要把两个navigationBar.barTintColor设置为不同的颜色才能出现上面gif中的效果了。

深究

UIViewControllerTransitionCoordinatorContext 的深入研究将重新开一篇blog。