最简单的方法是改变alpha,但是苹果的指南指出:
在iOS v5.0之前,当与导航控制器一起使用时,您只能对导航栏进行少量直接自定义。具体而言,修改barStyle、tintColor和translucent属性是可以的,但是绝不能直接更改UIView级别的属性,例如frame、bounds、alpha或hidden属性。
语言有点奇怪,因为它声明了iOS 5之前的情况,但它声明了你不能直接更改alpha值,而且从未说明现在允许这样做。
我不想让我的应用被拒绝。
如何像状态栏一样淡出导航栏?
解决这个问题很有趣。
本来应该非常简单:使用UIView transitionWithView
在导航栏的隐藏和非隐藏状态之间执行交叉淡入淡出,如公共API setNavigationBarHidden:animated:
所设定的那样。实际上,这对于"淡出"导航栏是有效的,但将其淡入时会出现问题。问题在于,无论是否在调用setNavigationBarHidden:animated:
时指定了动画,导航栏都会滑动到位,而UIView +transitionWithView:
不会动画化可动画属性(例如frame
),除非你指定UIViewAnimationOptionAllowAnimatedContent
。
对我来说,这意味着内部的UINavigationController
无论在调用setNavigationBarHidden:animated:
时指定了动画,仍会在一个动画块中重新定位UINavigationBar
。当animate:
设置为NO
时,此动画块的持续时间可能设置为'0'。
解决方案是在交叉淡入淡出转换之前以可见状态(不带动画)设置导航栏。这确保了导航栏从正确位置开始交叉淡入淡出,并且交叉淡入淡出仅会显示新的非隐藏状态。
我的示例项目是标准的单视图应用程序。在Storyboard中,有一个UINavigationController
,它是入口点。我将此控制器的UINavigationBar
的条形样式设置为黑色半透明(类似于照片应用)。导航控制器的rootViewController
是一个简单的UIViewController
,具有填充整个边界的UIImageView
(也像照片应用一样)。我在视图上添加了一个 UITapGestureRecognizer
来调用以下代码,在视图控制器中:
- (IBAction) onShowHideNavbar: (id) sender
{
BOOL hide = !self.navigationController.navigationBarHidden;
if ( !hide)
{
[self.navigationController setNavigationBarHidden: hide animated: NO];
}
[UIView transitionWithView: self.navigationController.view
duration: 1
options: UIViewAnimationOptionTransitionCrossDissolve
animations: ^{
[self.navigationController setNavigationBarHidden: hide animated: NO];
}
completion: nil ];
}
话虽如此,我认为您直接操作UINavigationBar
的隐藏或透明度属性不会导致任何问题(Apple拒绝)。文档警告不要触摸它们,因为它们由UINavigationController管理,并更改它们可能会有看不见的后果。但在我看来,它们是公共API,因此使用它们不应该成为被拒绝的原因。
UINavigationBar
实例替换它;-) DetailViewController
的viewDidLoad
方法:- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self configureView];
self.fakeBar = [[UINavigationBar alloc]initWithFrame:self.navigationController.navigationBar.bounds];
UIBarButtonItem *back = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(back)];
UINavigationItem *backItem = [[UINavigationItem alloc]initWithTitle:@"Back"];
backItem.leftBarButtonItem = back;
[self.fakeBar pushNavigationItem:backItem animated:YES];
[self.view addSubview:self.fakeBar];
}
如果您继续阅读,这是在引用后的下一段:
在iOS v5.0及更高版本中,您可以使用“自定义栏外观”中列出的方法来自定义栏的外观。您可以使用外观代理([UINavigationBar appearance])自定义所有导航栏的外观,也可以只自定义单个栏。
点击链接(Customizing the Bar Appearance)将显示以下内容:
自定义栏外观
tintColor 属性
– backgroundImageForBarMetrics:
– setBackgroundImage:forBarMetrics:
– titleVerticalPositionAdjustmentForBarMetrics:
– setTitleVerticalPositionAdjustment:forBarMetrics:
titleTextAttributes 属性
因此,在iOS v5.0及更高版本中,这是您可以(合法地)更改的列表。您可能可以通过更改tintColor的alpha或背景图像来使其看起来像是淡出(然后隐藏它),但我怀疑它不会看起来很对。尝试一下可能还是值得的。
你可能不能轻松地淡化导航栏,但是你可以轻松地淡化一个导航栏的图片。所以你可以做一件事情,就是创建一个导航栏的图像,用你的图像替换导航栏,然后通过透明度对图像视图进行动画处理,使其逐渐消失。或者你也可以反过来:在导航栏上方放置一个图像视图,并淡入一个代表导航栏后面内容的图像。