我如何动画UINavigationBar setBackgroundImage:forBarMetrics:?

时间:2013-01-30 11:20:35

标签: ios objective-c ios6 uinavigationcontroller

当按下某个控制器时,我正在更改导航栏的背景图像。我想为这种变化制作动画。我可以使用以下代码执行此操作:

[UIView transitionWithView:self.navigationController.navigationBar
                  duration:0.3f
                   options:UIViewAnimationOptionTransitionCrossDissolve
                animations:^{
    [self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"now-playing-nav-bar.png"]
                                                 forBarMetrics:UIBarMetricsDefault];
} completion:NULL];

但是,这会阻止应用于navigationBarTitleUIBarButtonItem的默认推送动画。

如何让背景更改和推送动画一起使用?

我希望尽可能使用vanilla作为解决方案。

PS:我无法使用tintColor,因为背景已经过纹理化。

3 个答案:

答案 0 :(得分:26)

仅在iOS 6上测试

我使用Core Animation解决了它:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    CATransition *animation = [CATransition animation];
    animation.duration = 0.3;
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    animation.type = kCATransitionFade;

    [self.navigationController.navigationBar.layer addAnimation:animation forKey:nil];

    [UIView animateWithDuration:0.3 animations:^{
        [self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"now-playing-nav-bar.png"] forBarMetrics:UIBarMetricsDefault];
    }];
}

viewWillDisappear:中做同样的事情,你很高兴。

答案 1 :(得分:5)

这适用于iOS 9:

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    changeNavigationBackground()
}

func changeNavigationBackground() {
    // navigationBar should always exist if the view controller is in a UINavigationController
    guard let navigationBar = navigationController?.navigationBar else { return }

    // the current navigation background
    guard let imageView = navigationBar.subviews.filter({ $0 is UIImageView }).first else { return }
    let image = UIImage(named: "navigation_background")
    let newImageView = UIImageView(image: image)
    newImageView.frame = imageView.frame
    newImageView.alpha = 0.0
    navigationBar.insertSubview(newImageView, belowSubview: imageView)

    transitionCoordinator()?.animateAlongsideTransition({ (context) in
        imageView.alpha = 0.0
        newImageView.alpha = 1.0
    }, completion: { (context) in
        newImageView.removeFromSuperview()
        navigationBar.setBackgroundImage(image, forBarMetrics: .Default)
        imageView.alpha = 1.0
    })
}

如果可能,我尽量避免使用Core Animation,所以我只使用了视图并在转换过程中更改了它们的alpha值。

答案 2 :(得分:0)

如果没有过渡动画,推送动画是否有效?如果是,可能需要在更改导航栏图像的块中自行完成推送动画。