Has anyone ever encountered an issue where a navigation bar with custom background is shifted to the top when the screen is transitioning between a hidden status bar and a shown status bar?
The problem is this issue doesn't happen with a debug build, but it does happen with a release build. I'm really confused because I'm not using any conditionals for UI behaviors.
Additionally, this will only happen if the app is entering a foreground mode in a "fullscreen" state. Then I switched from a fullscreen state to a non-fullscreen state, the problem occurs.
Update: this issue occurs regardless of whether I'm using a custom background or not.
I'm using iOS 4.3 SDK running on iOS 4.3.3.
I do this transition like this:
UIWindow *window = [[UIApplication sharedApplication] firstWindow];
[window addMoveInTransitionWithDuration:0.5 subtype:kCATransitionFromBottom];
[self.fullScreenViewController.view removeFromSuperview];
[self presentNonFullScreenViewAnimated:NO];
This is the firstWindow method:
- (UIWindow *)firstWindow
{
if ([self.windows count] > 0)
return [[self windows] objectAtIndex:0];
return [self keyWindow];
}
This is the presentNonFullScreenViewAnimated: method
- (void)presentNonFullScreenViewAnimated:(BOOL)animated
{
[[UIApplication sharedApplication] setStatusBarHidden:NO];
[self.navigationController setNavigationBarHidden:NO animated:NO];
NonFullScreenViewController *viewController = [[NonFullScreenViewController alloc] init];
[self.navigationController pushViewController:viewController animated:animated];
[viewController release];
}
Related
So I have an app which mainly consists of web views. Everyhting is working fine, I have my status bar and navigation bars configured as I like.
The only issue is, when I go to a website that has a "Choose File" option, it opens the Saved Images to select a image (no issue here), then when I tap on the saved images table cell, the status bar text goes from white to black and I am unable to revert back.
I have tried calling UIStatusBarStyleLightContent in viewDidAppear, viewDidDisappear, etc which solves it reverting, but only on that single view it changes.
Any ideas on how to keep it UIStatusBarStyleLightContent all the time? I should note I have [UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; declared in the App Delegate, and UIViewControllerBasedStatusBarAppearance set to NO.
Thanks.
UPDATE with screenshots:
UPDATE 7/14
I managed to get it somewhat working, but in turn it broke the default video player status bar text. Plus it just won't hide to begin with.
I used:
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:YES];
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
}
-(void) viewDidDisappear:(BOOL)animated {
[self.webView stopLoading];
[self.navigationController setNavigationBarHidden:YES];
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
}
FINAL UPDATE??
Not pretty, but i managed to somewhat get the effect all together between the video player and image uploader.
-(void) viewDidDisappear:(BOOL)animated {
[self.webView stopLoading];
[self.navigationController setNavigationBarHidden:YES];
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
[[UIApplication sharedApplication] setStatusBarHidden:YES
withAnimation:UIStatusBarAnimationNone];
}
Set "View controller-based status bar appearance” to NO in your info.list file;
Add this code
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
to -application:didFinishLaunchingWithOptions: of the AppDelegate.m.
I hope your problem will be solved
For the life of me, I cannot figure out how to get rid of the white bar at the top of my app.
http://cl.ly/image/3Z2I1x0H3H17
I am currently using a navigation controller as the root view. I've also tried just having a UIViewController as the root view.
In the first UIViewController I have tried:
- (void)viewWillAppear:(BOOL)animated {
[[self navigationController] setNavigationBarHidden:YES animated:NO];
}
This does nothing.
I have also tried:
- (BOOL)prefersStatusBarHidden {
return YES;
}
Which hides the status icons (battery, cell connection indicator).
But really, I just want all that white space gone.
Try:
[[UIApplication sharedApplication] setStatusBarHidden:YES];
Or set Status Bar to 'None' in the XIB.
In viewDidLoad add this code:
//checks if device is running iOS 7 (or newer) or iOS 6 (or older)
if ([self respondsToSelector:#selector(setNeedsStatusBarAppearanceUpdate)]) {
[self performSelector:#selector(setNeedsStatusBarAppearanceUpdate)];
} else {
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
}
Then add this method:
- (BOOL)prefersStatusBarHidden {
return YES;
}
In iOS 6, I was using the following code to push a UIImagePickerController, of source type UIImagePickerControllerSourceTypeCamera, and to show its navigation bar. I wanted to show the navigation bar because after taking the image, I'm pushing another VC that allows the user to set some attributes in the database.
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
{
cameraController = [[UIImagePickerController alloc] init];
cameraController.delegate = self;
cameraController.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:cameraController animated:YES completion:NULL];
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault animated:YES];
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide];
cameraController.topViewController.title = #"Add";
cameraController.navigationBar.translucent = NO;
cameraController.navigationBar.barStyle = UIBarStyleDefault;
[cameraController setNavigationBarHidden:NO animated:NO];
}
In iOS 7 this code no longer shows the navigation bar. Does anyone know if there's a way to to get the navigation bar back for UIImagePickerController, of source type UIImagePickerControllerSourceTypeCamera?
Guess what? When imagePicker presents, it's automatic set to hidden....
All you need to do is setHidden:NO in next runloop. Like:
[self presentModalViewController:imagePicker animated:YES];
[self performSelector:#selector(showNavigationBar:) withObject:imagePicker afterDelay:0];
- (void)showNavigationBar:(UIImagePickerController*)imagePicker {
[imagePicker setNavigationBarHidden:NO];
}
#LeverkusenFan's solution works well. But instead of using a hack such as a run loop, you use the completion handler of presentViewController to achieve that effect.
[self presentViewController:cameraController animated:YES completion:^{
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone];
cameraController.topViewController.title = #"Add";
cameraController.navigationBar.translucent = NO;
cameraController.navigationBar.barStyle = UIBarStyleDefault;
[cameraController setNavigationBarHidden:NO animated:NO];
}];
In fact a better solution that avoids the weird animation when the navigation bar shows up and which works well when you press the back button on the nav bar is as follows:
In the delegate for the UIImagePickerController implement the following function.
- (void) navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if (navigationController == self.cameraController && navigationController.viewControllers.count == 1) {
// When showing the ImagePicker update the status bar and nav bar properties.
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone];
navigationController.topViewController.title = self.cameraTitle;
navigationController.navigationBar.translucent = NO;
navigationController.navigationBar.barStyle = UIBarStyleDefault;
[navigationController setNavigationBarHidden:NO animated:animated];
}
}
This function will get called when the ImagePicker is shown and we only make the changes for the rootViewController of the ImagePicker (i.e. the camera screen).
I'm looking for the name of the class Apple uses to present a number of Images in full screen (similar to the AppStore-App on iPad when you tap the preview images of any App. In the bottom of the view is a bar with little preview Images from all the Images).
If this is a public class, how is it called and is it available for iPhone as well?
Ok so I have created my own ImageFullScreenPresenter.
What is important for anybody trying to build their own ImageFullScreenPresenter is to make it a subclass of UIViewController.
PKImageFullScreenPresenter *pkImageFullScreen = [[[PKImageFullScreenPresenter alloc] initWithNibName:#"PKImageFullScreenPresenter" bundle:nil imageArray:myImageArray] autorelease];
AppDelegate *appDel = (AppDelegate *)[UIApplication sharedApplication].delegate;
UIViewController *rootViewController;
if (DEVICE_IS_IPAD) {
//since the splitviewcontroller is the rootviewcontroller on ipad i set it as my temporary rootViewcontroller for ipad
rootViewController = appDel.splitViewController;
}
if (DEVICE_IS_IPHONE) {
//on iphone i need the tabbarcontroller as temporary rootviewcontroller
rootViewController = appDel.tabBarController;
}
//set the alpha to zero, so it can fade in animated
pkImageFullScreen.view.alpha = 0;
//save the temporary rootViewController, so I can set it back when dissmissing the ImageViewController
pkImageFullScreen.superViewController = rootViewController;
//hide the status bar
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationFade];
//setting black backgroundcolor
[UIApplication sharedApplication].keyWindow.backgroundColor = [UIColor blackColor];
//init the fullscreencontroller as rootview
[[UIApplication sharedApplication].keyWindow setRootViewController:[[[UINavigationController alloc] initWithRootViewController:pkImageFullScreen] autorelease]];
//smooth fade animation
[UIView animateWithDuration:.5f
animations:^(void){
pkImageFullScreen.view.alpha = 1;
}];
Doing so, allows me to present the ImageFullScreenPresenter on iPhone and iPad, no matter you are using a window-based app, a splitViewController on iPad or whatever.
When dismissing the ImageFullScreenPresenter i set the temporary saved rootViewController back with an animation:
- (void)closeView:(id)sender{
[UIView animateWithDuration:.5f
animations:^(void){
self.view.alpha = 0;
}completion:^(BOOL finished){
//show the statusbar again
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationFade];
//setting the statusbarstyle
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackTranslucent];
//set the backgroundcolor for the window
[UIApplication sharedApplication].keyWindow.backgroundColor = GLOBAL_TINT_COLOR; //my custom color vor all GUI Objects
//set the temporary rootViewController back
[[UIApplication sharedApplication].keyWindow setRootViewController:superViewController];
//sometimes the navigationbar hides the statusbar, the following two lines help me out
[[UIApplication sharedApplication].keyWindow.rootViewController.navigationController setNavigationBarHidden:YES];
[[UIApplication sharedApplication].keyWindow.rootViewController.navigationController setNavigationBarHidden:NO];
}];
}
I dont know if this is the right way to go, but it works perfectly finefor me. I do not have to worry abput any rotation issues like I would have when i directly add this to [UIApplication sharedApplication].keyWindow.
I hope this helps others who try do achieve the same :)
I have two simple UIViewControllers, their views are 320 x 460 with status bars. I do in AppDelegate
self.window.rootViewController = [[[SimpleController alloc] init] autorelease];
[self.window makeKeyAndVisible];
In SimpleController I have a button that does
- (IBAction) switchToVerySimpleController
{
[UIView transitionWithView: [[UIApplication sharedApplication] keyWindow]
duration: 0.5
options: UIViewAnimationOptionTransitionFlipFromLeft
animations:^{ [[UIApplication sharedApplication] keyWindow].rootViewController = [[[VerySimpleController alloc] init] autorelease]; }
completion: NULL];
}
The new view (VerySimpleController.view) is filled with a blue color. After animation new view is shown with a tiny white stripe (with the size of a status bar) at the bottom and then it jumps down into place. Why is it happening and how to avoid that? I suppose its status bar to blame, and I tried to set statusBar = Unspecified in IB for both views, but it doesn't help.
UPDATE:
When I hide statusBar (thru setting in .info file) from the start, no view adjustment occurs. But still... I need to show statusBar and I need that animation working properly.
When a rootViewController is assigned to a window, a new frame is assigned to the rootViewController's view if a status bar is present. This is so that the rootViewController's
view won't be hidden under the status bar.
Since you're setting the window's rootViewController inside the animation block, the new frame assignment gets animated as well.
To not show the jump you might set the frame of the rootViewController's view before the animation with something like this:
- (IBAction) switchToVerySimpleController
{
CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
VerySimpleController *vsc = [[[VerySimpleController alloc] init] autorelease];
vsc.view.frame = CGRectMake(vsc.frame.origin.x,
statusBarFrame.size.height,
vsc.frame.size.width,
vsc.frame.size.height);
[UIView transitionWithView: [[UIApplication sharedApplication] keyWindow]
duration: 0.5
options: UIViewAnimationOptionTransitionFlipFromLeft
animations:^{ [[UIApplication sharedApplication] keyWindow].rootViewController = vsc }
completion: NULL];
}
It seems that this issue still sometimes happen and it's probably a bug.
To avoid this 'jump' add this code to the viewWillAppear method of the view controller which needs to be shown:
swift
navigationController?.navigationBar.layer.removeAllAnimations()
objective-c
[self.navigationController.navigationBar.layer removeAllAnimations];
The transition will now finish without the 'jump'.