如何从半透明平滑过渡到不透明的UINavigationBar iOS?

时间:2015-03-27 18:06:51

标签: ios objective-c uinavigationbar

在视图之间转换时,我在iOS 7和8上重新配置UINavigationBar时遇到了问题。

我的应用程序目前包含以下UIViewController流程:

VC1 - > VC2 - > VC3

在此流程中

  • VC1是主屏幕,并且不透明 UINavigationBar
  • VC2有半透明 UINavigationBar
  • VC3回归不透明 UINavigationBar

我遇到的问题是这些视图之间的转换看起来都非常草率。首先,我尝试了以下内容:

VC2中的

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

    // configure appearance
    [self.navigationController.navigationBar configureTranslucentAppearance];
}

在VC1和VC3中

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

    // configure appearance
    [self.navigationController.navigationBar restoreDefaultAppearance];
}

以下是上面列出的两个辅助函数的实现:

- (void)restoreDefaultAppearance {
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];

    [self setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor JTTextNavBar]}];
    [self setTintColor:[UIColor JTTextNavBar]];
    [self setBarTintColor:[UIColor JTBackgroundNavBarWithAlpha:1.0]];
    [self setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
    [self setBackgroundColor:[UIColor JTBackgroundNavBarWithAlpha:1.0]];
    [self setShadowImage:[UIImage navigationBarShadowImage]];
    [self setTranslucent:NO];
}

- (void)configureTranslucentAppearance {
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];

    [self setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
    [self setBackgroundColor:[UIColor clearColor]];
    [self setShadowImage:[UIImage new]];
    [self setTranslucent:YES];
}

这是处理此转换的最基本方法。它有以下视觉文物:

  • 从VC1出发时 - > VC2一旦开始转换,导航栏就会变黑。动画正常完成enter image description here
  • 从VC2出发时 - > VC1导航栏会在segue有时间完成之前立即更改为应用程序默认颜色。 enter image description here
  • 从VC2出发时 - > VC3导航栏立即从半透明变为app导航栏颜色,然后是菜单项和VC体动画。enter image description here
  • 从VC3出发时 - > VC2导航栏立即变黑并保持这种状态直到segue完成。 enter image description here

这些过渡看起来都不好看。理想情况下,我希望视图与新的UINavigationBar一起平滑过渡,但我看到成功完成此操作的唯一方法是手动为每个xib添加工具栏。

有什么建议吗?如果这种描述令人困惑,请道歉:(

修改:为每个列出的转换添加了UINavigationBarUIViewController顶部的裁剪图像。

11 个答案:

答案 0 :(得分:15)

您看到的黑色是UINavigationController's视图的背景色。最小化观察的一种方法是将该视图的背景颜色操纵为传出/传入视图控制器视图的颜色。如果您使用纯色,这很有效。另一种方法是使用UIViewController.extendedLayoutIncludesOpaqueBars = YES;

将视图扩展到不透明导航栏后面

答案 1 :(得分:14)

我终于找到了一个不错的解决方案!

似乎没有一种正确的方法可以平滑地从不透明转换为透明UINavigationBar但是您可以从具有可见状态栏的视图控制器平滑过渡到具有隐藏状态栏的视图控制器

这会打开一个可能的解决方法,即在上面的 VC2 viewWillAppear中添加以下内容:

[self.navigationController setNavigationBarHidden:YES animated:YES];

完成后,手动将UINavigationBar添加到xib并将其配置为透明(并添加所有必需的UIBarButtonItem和视图)。

如果所有内容都已正确连接,则从 VC1 转换为 VC2 会以与视图转换相同的速度隐藏UINavigationBar VC2 < / strong>将显示嵌入式UINavigationBar

注意:为了使其正常工作,您必须确保可以从 VC2 访问的viewWillAppear视图控制器中您可以通过以下方式重置UINavigationBar以显示(如有必要)

[self.navigationController setNavigationBarHidden:NO animated:YES];

TL; DR - 手动将UINavigationBar添加到透明导航栏视图控制器,并在其viewWillAppear中隐藏默认值setNavigationBarHidden:animated:

答案 2 :(得分:4)

将UIWindow背景颜色设置为导航栏的tintColor。

答案 3 :(得分:3)

总是使用半透明,再添加一个带有下面颜色的uiview并为它设置alpha动画?

答案 4 :(得分:1)

我在几乎完全相同的问题上挣扎。使用导航栏或工具栏作为模糊,确实没有任何平滑过渡。我发现*的最佳选择是从视图中制作图像,然后使用该图像进行过渡。特别是如果您只是需要它来进行转换,它只是最便宜的选项仍然提供了很棒的UI / UX。

*需要注意的是,当您拍摄快照,屏幕截图或将UIView栅格化为图像时,导航栏和工具栏中的某些UI效果不会显示。如果用于过渡,这可以忽略不计。

答案 5 :(得分:1)

您只需使用UIView即可创建自己的导航栏,这样您就可以完全控制其外观,布局,渐变等。 我不久前放弃了使用UINavigationBar,因为你正在发现它可能会很麻烦,现在我从来没有使用它。

我有一个根视图控制器,它有一个代表导航栏的UIView。如果我想做一些事情,比如添加一个后退按钮,更改颜色,显示导航栏或隐藏它,更改透明度等等,这些都由RVC控制,其他视图控制器调用RVC上的方法来更改导航酒吧取决于他们的外观要求。

RVC有一个容器视图,它是控制器视图的完整大小,其他视图控制器被加载到该视图中。 设置一切的一点配置,但是一旦完成了一个可以在每个使用导航栏的项目中使用的结构。

答案 6 :(得分:1)

所以我也在努力解决这个问题。

不幸的是,我没有成功通过故事板添加我自己的导航栏。相反,(我警告你这是hacky)我在ViewController中添加了一个视图,其中不透明的导航栏具有负边距并在导航栏下方扩展。

当按下带有透明导航栏的ViewController时,条形图会立即变为透明,但由于我直接在其后面放置了相同颜色的视图,因此更改并不明显。等瞧。

我所拥有的代码非常基本,用C#(Xamarin)编写,但出于完整性的原因....

  var backing = new UIView(new CGRect(0, -68, this.View.Frame.Width, 64f));
  backing.BackgroundColor = UIColor.Green;
  this.View.AddSubview(backing);

答案 7 :(得分:0)

更改背景颜色对我有用

window?.backgroundColor = Color.red.toUIColor()

答案 8 :(得分:0)

我还有一个解决方案..对于那些正在重构项目并且无法在任何地方添加导航栏的人。.这不是一个完美的解决方案,就像@alexgophermix一个。但也不错:

let transition = CATransition()
        transition.duration = 0.6
        transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
        transition.type = kCATransitionFade
        navigationController?.navigationBar.shadowImage = UIImage()
        navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
        navigationController?.navigationBar.isTranslucent = true
        navigationController?.navigationBar.layer.add(transition, forKey: nil)
        navigationController?.view.backgroundColor = .clear

我在viewDidLoad()中设置了导航栏,因此它在任何地方都可以使用,并且过渡略有不同。以我为例,我在某处设置了清晰的背景并放置了渐变图像。因此,这种微小的变化适用于所有地方。这种过渡并不明显,但看起来都不错:)

答案 9 :(得分:0)

就我而言,我所看到的黑色是导航栏的背景图像。我没有将其设置为newUser.save() ,而是将其设置为与nil内的透明导航栏后面的视图的背景色相同:

viewWillAppear

然后,在let image = UIImage(color: .white) navigationController?.navigationBar.setBackgroundImage(image, for: .default) willMove内部,将其还原为原始颜色。

答案 10 :(得分:-1)

YPNavigationBarTransition是一个可配置的框架动画导航栏。

YPNavigationBarTransition使用两个假导航栏(确实是UIToolBar)来模拟条形转换,同时使真正的导航栏变得透明。

  1. 将您自己的UINavigationController子类化,并在其中嵌入transitioncenter,如YPNavigationController

  2. 分别为您的内容控制器实施YPNavigationBarProtocol

  3. 完成。

  4. 完整的演示包含在回购中,请查看详细信息。