UINavigationBar如何从半透明平滑过渡到不透明iOS?
How to transition smoothly from translucent to opaque UINavigationBar iOS?
我 运行 在视图之间转换时在 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 开始转换时,导航栏会变黑。动画正常完成
- 从 VC2 --> VC1 开始时,导航栏会在 segue 有时间完成之前立即更改为应用程序默认颜色。
- 从 VC2 --> VC3 开始时,导航栏会立即从半透明变为应用程序导航栏颜色,然后菜单项和 VC 主体动画进入。
- 从 VC3 --> VC2 开始时,导航栏会立即变黑并保持这种状态,直到转场完成。
None 这些过渡效果看起来不错。理想情况下,我希望视图能够随着它们的新 UINavigationBar
顺利过渡,但我看到成功执行此操作的唯一方法是手动向每个 xib 添加工具栏。
有什么建议吗?如果此描述令人困惑,我们深表歉意:(
编辑: 为每个列出的转换添加 UINavigationBar
和 UIViewController
顶部的裁剪图像。
我一直在努力解决几乎相同的问题。使用导航栏或工具栏作为模糊确实没有任何平滑的过渡。我发现的最佳选择* 是从视图中制作图像,然后使用该图像进行过渡。特别是如果你只需要它来进行过渡,它几乎是最便宜的选择,但仍然提供了很好的 UI/UX.
*需要注意的是,当您拍摄快照、屏幕截图或将 UI 视图栅格化为图片。如果用于过渡,则可以忽略不计。
您可以仅使用 UIView 创建自己的导航栏,这样您就可以完全控制其外观、布局、淡入淡出等。
不久前我放弃了使用 UINavigationBar,因为它可能会很痛苦,正如您所发现的那样,现在我从未使用过它。
我有一个根视图控制器,它有一个代表导航栏的 UIView。如果我想做一些事情,比如添加后退按钮、更改颜色、显示或隐藏导航栏、更改透明度等,这些都由 RVC 和 RVC 上的其他视图控制器调用方法来控制,以更改导航bar取决于他们的外观要求。
RVC 有一个容器视图,它是控制器视图的完整大小,其他视图控制器加载到其中。
进行一些配置即可设置所有内容,但一旦完成,它的结构就可以非常快速地用于每个使用导航栏的项目。
始终使用半透明,并在其下方添加一个带有颜色的 uiview 并为其 alpha 设置动画?
我终于找到了一个像样的解决方案!
似乎没有从不透明平滑过渡到透明的正确方法 UINavigationBar
但是您可以从具有可见状态栏的视图控制器平滑过渡到具有隐藏状态栏的视图控制器.
这打开了一个可能的解决方法,即在上面的 VC2 的 viewWillAppear
中添加以下内容:
[self.navigationController setNavigationBarHidden:YES animated:YES];
一旦你有了它,手动添加一个 UINavigationBar
到你的 xib 并将其配置为透明的(并添加所有必要的 UIBarButtonItem
和视图)。
如果一切都正确连接,从 VC1 到 VC2 将以与 UINavigationBar
相同的速度隐藏视图转换和 VC2 将显示为嵌入的 UINavigationBar
注意:要使其正常工作,您必须确保在 viewWillAppear
中可以从 访问的视图控制器VC2 您通过以下方式将 UINavigationBar
重置为可见(如有必要):
[self.navigationController setNavigationBarHidden:NO animated:YES];
TL;DR - 手动添加一个 UINavigationBar
到你的透明导航栏视图控制器,并在其 viewWillAppear
中通过 [=22 隐藏默认值=]
所以我也为此苦苦挣扎。
不幸的是,我没有成功通过故事板添加我自己的导航栏。相反,(我警告你这是 hacky)我在 ViewController 中添加了一个带有不透明导航栏的视图,该导航栏具有负边距并在导航栏下方延伸。
当按下带有透明导航栏的 ViewController 时,该栏会立即变为透明,但由于颜色相同的视图我直接放在它后面,所以变化并不明显。 Et voila.
我的代码非常基础,是用 C# (Xamarin) 编写的,但出于完整性原因....
var backing = new UIView(new CGRect(0, -68, this.View.Frame.Width, 64f));
backing.BackgroundColor = UIColor.Green;
this.View.AddSubview(backing);
您看到的黑色是 UINavigationController's
视图的背景色。最小化看到它的一种方法是将该视图的背景颜色操纵为传出/传入视图控制器视图的颜色。如果您使用纯色,这会很有效。另一种方法是使用 UIViewController.extendedLayoutIncludesOpaqueBars = YES;
将视图扩展到不透明的导航栏后面
将 UIWindow 背景颜色设置为导航栏的 tintColor。
YPNavigationBarTransition 是一个可配置的动画导航栏框架。
YPNavigationBarTransition 使用两个伪造的导航栏(实际上是 UIToolBar)来模拟栏过渡,同时使真正的导航栏透明。
将您自己的 UINavigationController 子类化并在其中嵌入过渡中心,如 YPNavigationController
分别为您的内容控制器实施YPNavigationBarProtocol。
完成。
repo 中包含完整的演示,请查看它了解更多详细信息。
更改背景颜色对我有用
window?.backgroundColor = Color.red.toUIColor()
我还有一个解决方案..对于那些现在正在重构项目并且无法在任何地方添加导航栏的人..这不是一个完美的解决方案,就像@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() 中设置我的导航栏,所以这在任何地方都有效,并且过渡略有不同。在我的例子中,我在某处设置了清晰的背景并放置了一个渐变图像。所以这个小改动适用于任何地方。这种转变不是很明显,但看起来也不坏 :)
就我而言,我看到的黑色是导航栏的背景图像。我没有将其设置为 nil
,而是将其设置为与 viewWillAppear
:
内透明导航栏后面的视图的背景颜色相匹配
let image = UIImage(color: .white)
navigationController?.navigationBar.setBackgroundImage(image, for: .default)
然后,在 willMove
和 viewWillDisappear
里面,我把它恢复到原来的颜色。
我 运行 在视图之间转换时在 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 开始转换时,导航栏会变黑。动画正常完成
- 从 VC2 --> VC1 开始时,导航栏会在 segue 有时间完成之前立即更改为应用程序默认颜色。
- 从 VC2 --> VC3 开始时,导航栏会立即从半透明变为应用程序导航栏颜色,然后菜单项和 VC 主体动画进入。
- 从 VC3 --> VC2 开始时,导航栏会立即变黑并保持这种状态,直到转场完成。
None 这些过渡效果看起来不错。理想情况下,我希望视图能够随着它们的新 UINavigationBar
顺利过渡,但我看到成功执行此操作的唯一方法是手动向每个 xib 添加工具栏。
有什么建议吗?如果此描述令人困惑,我们深表歉意:(
编辑: 为每个列出的转换添加 UINavigationBar
和 UIViewController
顶部的裁剪图像。
我一直在努力解决几乎相同的问题。使用导航栏或工具栏作为模糊确实没有任何平滑的过渡。我发现的最佳选择* 是从视图中制作图像,然后使用该图像进行过渡。特别是如果你只需要它来进行过渡,它几乎是最便宜的选择,但仍然提供了很好的 UI/UX.
*需要注意的是,当您拍摄快照、屏幕截图或将 UI 视图栅格化为图片。如果用于过渡,则可以忽略不计。
您可以仅使用 UIView 创建自己的导航栏,这样您就可以完全控制其外观、布局、淡入淡出等。 不久前我放弃了使用 UINavigationBar,因为它可能会很痛苦,正如您所发现的那样,现在我从未使用过它。
我有一个根视图控制器,它有一个代表导航栏的 UIView。如果我想做一些事情,比如添加后退按钮、更改颜色、显示或隐藏导航栏、更改透明度等,这些都由 RVC 和 RVC 上的其他视图控制器调用方法来控制,以更改导航bar取决于他们的外观要求。
RVC 有一个容器视图,它是控制器视图的完整大小,其他视图控制器加载到其中。 进行一些配置即可设置所有内容,但一旦完成,它的结构就可以非常快速地用于每个使用导航栏的项目。
始终使用半透明,并在其下方添加一个带有颜色的 uiview 并为其 alpha 设置动画?
我终于找到了一个像样的解决方案!
似乎没有从不透明平滑过渡到透明的正确方法 UINavigationBar
但是您可以从具有可见状态栏的视图控制器平滑过渡到具有隐藏状态栏的视图控制器.
这打开了一个可能的解决方法,即在上面的 VC2 的 viewWillAppear
中添加以下内容:
[self.navigationController setNavigationBarHidden:YES animated:YES];
一旦你有了它,手动添加一个 UINavigationBar
到你的 xib 并将其配置为透明的(并添加所有必要的 UIBarButtonItem
和视图)。
如果一切都正确连接,从 VC1 到 VC2 将以与 UINavigationBar
相同的速度隐藏视图转换和 VC2 将显示为嵌入的 UINavigationBar
注意:要使其正常工作,您必须确保在 viewWillAppear
中可以从 访问的视图控制器VC2 您通过以下方式将 UINavigationBar
重置为可见(如有必要):
[self.navigationController setNavigationBarHidden:NO animated:YES];
TL;DR - 手动添加一个 UINavigationBar
到你的透明导航栏视图控制器,并在其 viewWillAppear
中通过 [=22 隐藏默认值=]
所以我也为此苦苦挣扎。
不幸的是,我没有成功通过故事板添加我自己的导航栏。相反,(我警告你这是 hacky)我在 ViewController 中添加了一个带有不透明导航栏的视图,该导航栏具有负边距并在导航栏下方延伸。
当按下带有透明导航栏的 ViewController 时,该栏会立即变为透明,但由于颜色相同的视图我直接放在它后面,所以变化并不明显。 Et voila.
我的代码非常基础,是用 C# (Xamarin) 编写的,但出于完整性原因....
var backing = new UIView(new CGRect(0, -68, this.View.Frame.Width, 64f));
backing.BackgroundColor = UIColor.Green;
this.View.AddSubview(backing);
您看到的黑色是 UINavigationController's
视图的背景色。最小化看到它的一种方法是将该视图的背景颜色操纵为传出/传入视图控制器视图的颜色。如果您使用纯色,这会很有效。另一种方法是使用 UIViewController.extendedLayoutIncludesOpaqueBars = YES;
将 UIWindow 背景颜色设置为导航栏的 tintColor。
YPNavigationBarTransition 是一个可配置的动画导航栏框架。
YPNavigationBarTransition 使用两个伪造的导航栏(实际上是 UIToolBar)来模拟栏过渡,同时使真正的导航栏透明。
将您自己的 UINavigationController 子类化并在其中嵌入过渡中心,如 YPNavigationController
分别为您的内容控制器实施YPNavigationBarProtocol。
完成。
repo 中包含完整的演示,请查看它了解更多详细信息。
更改背景颜色对我有用
window?.backgroundColor = Color.red.toUIColor()
我还有一个解决方案..对于那些现在正在重构项目并且无法在任何地方添加导航栏的人..这不是一个完美的解决方案,就像@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() 中设置我的导航栏,所以这在任何地方都有效,并且过渡略有不同。在我的例子中,我在某处设置了清晰的背景并放置了一个渐变图像。所以这个小改动适用于任何地方。这种转变不是很明显,但看起来也不坏 :)
就我而言,我看到的黑色是导航栏的背景图像。我没有将其设置为 nil
,而是将其设置为与 viewWillAppear
:
let image = UIImage(color: .white)
navigationController?.navigationBar.setBackgroundImage(image, for: .default)
然后,在 willMove
和 viewWillDisappear
里面,我把它恢复到原来的颜色。