可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
It seems the only way to remove a navigation bar with animation is via it sliding upward. I want it to fade, like in Photos.app.
It would be easiest to change the alpha, however Apple's guidelines state:
Prior to iOS v5.0, when used in conjunction with a navigation
controller, there are only a handful of direct customizations you can
make to the navigation bar. Specifically, it is alright to modify the
barStyle, tintColor, and translucent properties, but you must never
directly change UIView-level properties such as the frame, bounds,
alpha, or hidden properties directly.
The language is a little weird, as it states prior to iOS 5, but it stated you're not allowed to change the alpha value directly, and it never states you're allowed to now.
I don't want my app to get rejected.
How do I fade out the navigation bar like I would the status bar?
回答1:
This was a fun one to solve.
It should have been very straight-forward: use UIView transitionWithView
to perform a cross-fade between the hidden and non-hidden states of the navigation bar, as set by the public API setNavigationBarHidden:animated:
. In fact this works for "fading out" the navbar, but fading it back in had an issue. The issue was that the navbar would slide into place regardless of the fact that UIView +transitionWithView:
doesn't animate animatable properties (e.g. frame
) unless you specify UIViewAnimationOptionAllowAnimatedContent
.
To me this says that internally the UINavigationController
repositions the UINavigationBar
inside an animation block regardless of whether animating was specified in the call to setNavigationBarHidden:animated:
. The duration for this animation block is probably set to '0' when animate:
is set to NO
.
The solution is to set the navigation bar visible (sans animation) before the cross-fade transition. This ensures that the navigation bar begins the cross-fade in the correct position, and that the cross-fade will only reveal the new non-hidden state.
My sample project is a standard Single View Application. On the storyboard is a UINavigationController
, which is the entry point. I set the bar style for this controller's UINavigationBar
to black-translucent (similar to the Photos app). The navigation controller's rootViewController
is a simple UIViewController
with a UIImageView
filling the entire bounds (also like the Photos app). I added a UITapGestureRecognizer
on the view to invoke the following code, in the view controller:
- (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 ];
}
All this said, I don't think you'd get into any trouble (Apple Rejection) for messing with the hidden or alpha properties of the UINavigationBar
directly. The docs warn against touching these because they're managed by the UINavigationController and changing them might have unseen consequences. But In My Opinion they're public APIs and as such using them shouldn't be cause for rejection.
回答2:
You can't animate properties of the navigation bar of a UINavigationController legally.
However, you can show a navigation controller with hidden navigation bar (hiding it always or only on a specific view controller, as you prefer), and replace it with your "special" instance of UINavigationBar
;-)
I attach a sample project (I used an Xcode template to create it faster): FakeNavBar
Look at the viewDidLoad
method of the DetailViewController
:
- (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];
}
Here's a video of the final product on YouTube.
回答3:
A way around this (I don't know exactly how you are planning to animate to the next view or in what way you want to incorporate the fade) is to render the current view to a uiimage, make a full screen UIImageView with this image (basically replacing your existing UIView with a picture of it) Swap in your new view behind the image view and then fade out the image view.
You can also crop out just the UInavigationBar part of the image and fade that after the transition. This way you can apply any image effects to the 'UINavgationBar' without getting rejected by apple.
回答4:
I know of no Apple-sanctioned way to do this. I doubt you would be rejected for modifying the alpha value of the navigationBar, but like you, I don't know for certain.
You can of course implement your own navigation controller/navigation bar with which you can do anything you want. That is what I have done in my applications when I need to do something like this. Apple has been totally fine with that. Bonus points: Apple can change their controls as much as they want without breaking your layout if you use custom controls. This was recently a problem in certain areas of our application where the app looks VASTLY different in different versions of iOS (7).
Anyway, that's my 2 cents...
回答5:
If you keep reading, this is the next paragraph right after your quote:
In iOS v5.0 and later, you can customize the appearance of the bar
using the methods listed in “Customizing the Bar Appearance.” You can
customize the appearance of all navigation bars using the appearance
proxy ([UINavigationBar appearance]), or just of a single bar.
Clicking the link (Customizing the Bar Appearance) will show you this:
Customizing the Bar Appearance
tintColor property
– backgroundImageForBarMetrics:
– setBackgroundImage:forBarMetrics:
– titleVerticalPositionAdjustmentForBarMetrics:
– setTitleVerticalPositionAdjustment:forBarMetrics:
titleTextAttributes property
So in iOS v5.0 and later, that is the list that you can (legally) change. You might be able to play some games with the alpha of the tintColor or a background image in order to make it look like it is fading out (and then hide it) but I doubt that it will look quite right. Probably worth an attempt though.
回答6:
You may not be able to easily fade the navigation bar, but you can easily fade a picture of the navigation bar. So one thing you could do is to create an image of the nav bar, replace the nav bar with your image, and then animate the image view with alpha going to 0. Or you could do the opposite: position an image view on top of the nav bar, and fade in an image of whatever is supposed to be behind the nav bar.