Objective C Navigation Bar does not adjust when StatusBar changes - objective-c

We have a problem where the user is using our app on the iPhone and receives a call while on a view that has been presented by the rootviewcontroller and is covering the navigation controller and it's nav bar. The status bar for the call shows and pushes the current view down but when that view is removed from the superview, the status bar covers half of the navigation bar.
We have tried using a UIApplicationWillChangeStatusBarFrameNotification in the app delegate and then adjusting the size of the navigation controller and the navigation bar to no effect. We have also tried resetting the frame of the navigation controller and nav bar in the viewWillAppear function of the page that presents the view.
Can anyone tell us where we are going wrong?
In App Delegate we tried this
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self setupAppStyles];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor ugBlue];
UINavigationController *navController = [[UINavigationController alloc] init];
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
[self setUpNotifications];
return YES; }
-(void) setUpNotifications {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(statusFrameChanged:)
name:UIApplicationWillChangeStatusBarFrameNotification
object:nil];}
- (void)statusFrameChanged:(NSNotification*)note {
CGRect statusBarFrame = [note.userInfo[UIApplicationStatusBarFrameUserInfoKey] CGRectValue];
self.statusHeight = statusBarFrame.size.height;
UIScreen *screen = [UIScreen mainScreen];
CGRect viewRect = screen.bounds;
viewRect.size.height -= self.statusHeight;
viewRect.origin.y += self.statusHeight;
[[UINavigationBar appearance] setFrame:viewRect];
NSLog(#"The status frame has changed");
//[self.navController.view setFrame:viewRect];
self.navController.view.frame.size.height);}
We have also tried something similar in the views viewWillAppear functions also with no positive results. Any thoughts?

We were able to solve this problem. In the viewDidAppear of the view that called presentViewController we put
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat navBarHeight = self.navigationController.navigationBar.frame.size.height;
CGRect frame = CGRectMake(0.0f, statusSize, screenRect.size.width, navBarHeight);
[self.navigationController.navigationBar setFrame:frame];
When the status bar is shown

Related

How to get transparent navigation bar in root viewcontroller using UIappearance

In my app's delegate, I specify a transparent tool bar with (as suggested in an answer to question 18969248):-
The code is:
UINavigationBar *navigationBarAppearance = [UINavigationBar appearance];
navigationBarAppearance.backgroundColor = [UIColor clearColor];
[navigationBarAppearance setBackgroundImage:[[UIImage alloc] init] forBarMetrics:UIBarMetricsDefault];
navigationBarAppearance.shadowImage = [[UIImage alloc] init];
navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
This works for all view controllers pushed on to the navigation controller's stack, but not for the root view controller (which is loaded from a NIB).
How can I get transparency in the root view controller's navigation bar?
Maybe you should load your RootViewController programmatically through your AppDelegate this way, if you're using storyboard :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"yourStoryboard"
bundle: nil];
YourCustomRootViewController *customRootVC = (YourCustomRootViewController*) [mainStoryboard instantiateViewControllerWithIdentifier:#"firstAddProductViewController"];
// If you're not using storyboard, simply instantiate it this way
YourCustomRootViewController *customRootVC = [[YourCustomRootViewController alloc] initWithNibName:#"yourNib" bundle:nil];
/* In here, you want to add the code relative to the navigation bar of your rootVC */
[self.window setRootViewController:customRootVC];
}

Modifying UINavigation controller programatically in Xcode5

I have a programmatically generated UINavigationController applied to each of my ViewControllers but this UINavigationController is blank. I need to add some text, an image (if possible) and two buttons.
I have managed to do something similar with a very basic app that only has one ViewController and UINavigationController created in the normal manner but do not know what to do in regards to a programmatically generated one.
I am using storyboards in XCode5/iOS7.
Here is the code that generates the UINavigationController and launches the first ViewController:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
MainViewController* mainVC = [mainStoryboard instantiateInitialViewController];
UINavigationController *navVC = [[UINavigationController alloc] initWithRootViewController:mainVC];
[self.window setRootViewController:navVC];
[_window makeKeyAndVisible];
return YES;
}
I have tried things that I thought would be obvious like:
navVC.navigationBar.backgroundColor = [UIColor redColor];
To change the colour or:
[navVC setTitle:#"Test title"];
But nothing changes, the only way I could get the title to change was to change the title of mainVC
[mainVC setTitle:#"Test title"];
Changing the title in the MainViewController.m file itself does nothing.
So how do I modify the UINavigationController (navVC)?
Thanks,
You should be able to set an image to your navigation bar in this way:
UINavigationBar *navBar = navVC.navigationBar;
UIImage *image = [UIImage imageNamed:#"YourNavBarImg.png"];
[navBar setBackgroundImage:image];
and this to change the nav bar tint color:
[navVC.navigationBar setTranslucent:NO];
[navVC.navigationBar setBarTintColor:[UIColor redColor]];
about buttons (UIBarButtonItem) into nav bar:
// where "self" is your current viewcontroller
self.navigationItem.rightBarButtonItems = [NSArray arrayWithObjects:button1,button2, nil];

Second UIScreen causing problems with UIStoryboards

In my app delegate i set up another screen (for airPlay).
When i create a second window and assign the Second screen to it and run the app the TableView in my storyboard turns to a black colour. Its as if the tableView is not rendering correctly. I have isolated the problem to :
self.HDTVwindow.screen=[[UIScreen screens] objectAtIndex:1];
where the HDTVWindow is the second window for my airplay app. When i comment out this code the storyboard runs fine and my UITableView is nice and white. Am i confusing the storyboard by making two UIWindows in the appDelegate, even though they are assigned to different screens??
For my appDelegate see below.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if ([[UIScreen screens] count]>1)
{
CGRect frame = [[UIScreen screens]objectAtIndex:1].bounds;
self.HDTVwindow = [[UIWindow alloc] initWithFrame:frame];
UIImage* astonLogo=[UIImage imageNamed:#"AstonUni720p.png"];
UIImageView* astonLogoView=[[UIImageView alloc] initWithImage:astonLogo];
astonLogoView.frame=frame;
[self.HDTVwindow addSubview:astonLogoView];
self.HDTVwindow.hidden = NO;
self.HDTVwindow.screen=[[UIScreen screens] objectAtIndex:1];//PROBLEM!!
}
// Set Up Storyboard
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *mainViewController = [storyboard instantiateInitialViewController];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = mainViewController;
[self.window makeKeyAndVisible];
return YES;
}
The problem disapears when ran with the iPad and an apple TV, it seems there might a bug in the simulator. In future i shall always run my code on real ios devices.

My UIButton is not getting drawn to the screen

I am trying to actually test out how to hard code interfaces just using the single view template Xcode provides for now.
I have given AppDelegate.h an ivar and property of UILabel *titleLabel; and my AppDelegate.m code is declared in the -(void) did finish launching:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// Set the view controller as the window's root view controller and display.
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
UIButton *button = [UIButton buttonWithType: UIButtonTypeRoundedRect];
button.titleLabel.font = [UIFont systemFontOfSize: 12];
button.titleLabel.lineBreakMode = UILineBreakModeTailTruncation;
button.titleLabel.shadowOffset = CGSizeMake (1.0, 0.0);
[self.window addSubview: button];
}
I get a successful compile, but the button is not drawn on the screen--I just get the standard blank template running in the simulator. How do I get it to draw?
Your window appears to be uninitialized, and your function is returning too early. Try this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];
// Set the view controller as the window's root view controller and display.
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
UIButton *button = [UIButton buttonWithType: UIButtonTypeRoundedRect];
button.titleLabel.font = [UIFont systemFontOfSize: 12];
button.titleLabel.lineBreakMode = UILineBreakModeTailTruncation;
button.titleLabel.shadowOffset = CGSizeMake (1.0, 0.0);
[self.window addSubview: button];
return YES;
}
Remember that return immediately exits a function, and any code below it will not be executed.

View Controller Animation in Xcode

I need to animate a view when user click on the button. i am using the following code for animating
App Delegate
ViewController2 *vc2_controller = [[ViewController2 alloc]init];
UINavigationController *baseViewController = [[UINavigationController alloc]initWithRootViewController:vc2_controller];
[self.window addSubview:baseViewController.view];
self.window.rootViewController = vc2_controller;
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
[self.window addSubview:navigationController.view];
self.viewController = [[vc1controller alloc]initWithNibName:nil bundle:nil];
//ViewController1.m -- This is Working
[self.navigationController pushSlideViewController:self.navigationController];
I created function definition inside the category
//Category
- (void)pushSlideViewController:(UIViewController *)viewController
{
// NSLog(#"In Navigation Controller");
//[UIView transitionWithView:viewController.view duration:0.5 options:UIViewAnimationOptionTransitionFlipFromLeft animations:nil completion:nil];
CGRect screensize = [[UIScreen mainScreen]bounds];
[UIView animateWithDuration:0.5 animations:^{
NSLog(#"In View ANimatin");
CGRect current_rect = viewController.view.frame;
viewController.view.frame = current_rect;
current_rect.origin.x = screensize.size.width-50;
viewController.view.frame = current_rect;
}];
}
Now i am calling ViewController1.m from ViewController2.m -- Animation is Not Working
ViewController1 *view_control = [[ViewController1 alloc]init];
[self.navigationController popSlideViewController:view_control];
//Category
-(void)popSlideViewController:(UIViewController *)viewController
{
CGRect screensize = [[UIScreen mainScreen]bounds];
//NSLog(#"In Pop");
[UIView animateWithDuration:0.5 animations:^{
//View is not coming to original position.
CGRect current_rect = viewController.view.frame;
NSLog(#"In View ANimatin %f",current_rect.origin.x);
viewController.view.frame = current_rect;
current_rect.origin.x = 0.0;
viewController.view.frame = current_rect;
}];
}
Note: i am not using ios5 :-)
Thanks,
You're loading VC2 from VC1, which, as you say, works fine. Then you're trying to load VC1 from VC2, which is where the problem lies - VC1 is still loaded, behind VC2, so you just need to dismiss VC2 in a similar way to how you brought it up in the first place, just animate it back off the screen, remove it from the view, then release it (unless you released it when you showed it). Alternatively you could use the built-in methods,
presentViewController:animated:completion:
and
dismissViewControllerAnimated:completion:
which have their own animation.