Key window doesn't rotate - iphone

I have a UIViewTable with navigation bar. When I read data I display UIViewController with ActivityIndicator on top of the table. The problem is when I rotate device this top view is not rotating, I don't know why? :(
This is how I add top view with ActivityIndicator:
UIView *view = [[UIApplication sharedApplication] keyWindow];
[view addSubview:viewWithLoader.view];
This is how I remove it:
[viewWithLoader.view removeFromSuperview];
This is method from top view (with ActivityIndicator):
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}

after you call [self.window makeKeyAndVisible]; on your App delegate, the views that get the rotation notification, animation, etc, etc. are the subviews of that initial view.
It happen to me that I had a top bar that replaced the status bar. so I thought it will be a good idea to actually add it as a sub view of the key window. But that being the case resulted in the outcome you are experiencing.
You have 2 options
whoever owns that topview should take care of rotating it or remove/add it when a rotation occurs so it has the right orientation.
make that topview a subview of one of the views that ARE autorotating.
Both are really easy to implement but I found no. 2 is more visually attractive for the user.

I found solution :) I add this top view (with loader) as 'modal view' and rotation works fine in all views :)
...
[self presentModalViewController:ldr animated:YES];
...
[self dismissModalViewControllerAnimated:YES];

Related

Can two UIViewControllers use a single navigation bar?

In my iPhone app I am trying to have the allusion of having a single static navigation bar, so the title and buttons don't ever swipe across when switching views.
I can't think a way of doing it (simply at least), so do you have any suggestions? I need to have a static title and buttons up in the nav bar space (even if I don't use the UINavigationBar, but make something custom) so that when I do something such as push a view controller, when it swipes across my nav bar doesn't move and the buttons change function for the new view.
Edit
Ok, I have thought of a possible method. Each of my views have a secondary view in which gold the view contents, except the nav bar objects. Can I override the pop and push methods to just animate this subview on and off screen?
Just do a push as normal but set it to not animate.
i.e.
[self.navigationController pushViewController:newViewController animated:NO];
Then when you want to go back...
[self.navigationController popViewControllerAnimated:NO];
Then you can have two navigation bars but it will look like it's the same bar as it isn't animating.
EDIT TO ALSO ANIMATE IN THE VIEW AND KEEP THE NAV BAR
I'm not sure of the whole flow of the app but if you want to keep the nav bar and swipe the new UI in then you could create a scroll view (with paging) and put the views of each VC on different frames of the scroll view or something.
Why do you want to keep the nav bar still anyway? There is nothing wrong with animating the nav bar and keeping the same buttons etc on it.
Having said that, if you are using different VCs then the nav bar should change anyway to show the details (i.e. title) of the VC you are currently looking at.
ANOTHER MORE RADICAL APPROACH
OK, thinking laterally now :D
How about, you use the not animated push and pop (as above) but instead of just displaying the UI you can animate it in from the relevant side. (A singleton or a VC subclass which you then subclass for your UI could do this for you across all view controllers).
The next problem is that it will look like the UI has gone instantly blank before animating in the new UI so you need to animate out the old UI. This means both UIs (the old and the new) have to be on the screen at the same time.
You can get round this by converting the entire view of the old UI into an image (not hard to do will find a link) and then passing this image into the new VC. The new VC will then instantly display this image and animate it out of the screen at the same time as animating its own UI onto the screen.
Really not as hard to do as it sounds. Especially if you subclass UIViewController ad give it a function animateUI and a property oldUIImage and direction. Then you can override viewWillAppear in this class to do the animation for you. Then the only thing you have to do is give each VC an image and a direction when you push/pop to it.
This is just giving the illusion of what you're after and means you can still keep a fairly simple object model and flow of the app.
...or something.
Just a riff on #Fogmeister's good idea...
In the presenting view controller, get self.view's image by implementing the suggestion here. Then, when it's time to present...
UIImage *image = [self makeImage]; // what it was called in the other post, consider a better name
MyViewController *newVC = [[MyViewController alloc] initWithNibName:#"MyViewController" bundle:nil];
newVC.presentationImage = image;
[self.navigationController pushViewController:newVC animated:NO];
In MyViewController, give it a UIImage property called presentationImage, then ...
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
UIImageView *imageView = [[UIImageView alloc] initWithImage:self.presentationImage];
imageView.frame = self.view.bounds;
imageView.tag = 128;
[self.view addSubview:imageView];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
UIImageView *imageView = (UIImageView *)[self.view viewWithTag:128];
[UIView animateWithDuration:0.5 animations:^{
imageView.frame = CGRectOffset(imageView.frame, -self.frame.size.width, 0);
}];
}
FYI - I didn't test or even compile this. Just liked the idea and decided to stretch my fingers.
To do this in a "clean" way, you'd need to abandon UINavigationController and write a custom container controller that does not push new navigation items onto it's navigation bar when pushing a new view controller (or allows you to push the navigation item in a non-animated fashion while animating the push of the view controllers views).
However doing this will take some time. If you decide to do this, i recommend the WWDC Session on UIViewController containment.
Another alternative that springs to my mind is to (by subclassing or method swizzling) alter the behaviour of UINavigationController to push the navigation items non-animated while animating the viewcontroller-push.
I have in no way tested this, but overriding push (and pop respectively) in a subclass like this might work:
- (void)pushViewController:(UIViewController *)vc animated:(BOOL)animated {
[super pushViewController:vc animated:animated];
[self.navigationBar setItems:self.navigationBar.items animated:NO];
}
If this method doesn't work, it might be worth inspection what animations are going on inside the nav bar directly after the call to pushViewController:animated:. Maybe you can cancel some animations to go to the final state directly.

Navigation Controller inside UIView

Whe I create a new UIViewController and try to put inside a NavigationController in the usual way (drag-drop in the xib and create the outlet), I show the Navigationcontroller with:
[self.view addSubview:navigationController.view]
The result is a Navigation Bar with a little band in the upper part (seems displaced down), (i can't post the image now but is like 20px empty space)
I tried to put the navigation controller on the top window:
[[[UIApplication sharedApplication] keyWindow] addSubview:navigationController.view];
And it worked, but I'm unable to come back the initial screen whe I execute:
[navigationController.view removeFromSuperview]
or
[self dissmissModalViewControllerAnimated:YES];
It is possible to solve this?
UINavigationController* nav=[[UINavigationController alloc]init];
nav.navigationBar.frame=CGRectMake(0, 0, 320, 44);
NSLog(#"desc=%#",[nav.navigationBar description]);
[self.view addSubview:nav.navigationBar];
Try with above code. it will hide unnecessary space.
Thanks
20 pixels sounds like the status bar. Make sure in your nib that the status bar option for the view is set to None. Hope that Helps!

Going out of movie player fullscreen causes the navigationController's navigationBar to move behind status bar

I have a MPMoviePlayerController view added as a subview on my ViewController.
I am using layoutSubviews to resize subviews during orientation changes.
When I play the movie in fullscreen, and, while still in fullscreen, rotate the phone, sometimes when I exit full screen, my navigation Bar "hides" halfway below the status bar, as if the origins for both are the same with the status bar on top.
I'm wondering if I'm doing something wrong... can anyone help?
Thanks!
Don't change your navigationBar's frame read bellow from Apple's docs:
The navigation controller manages the creation, configuration, and
display of the navigation bar and optional navigation toolbar. It is
permissible to customize the navigation bar’s appearance-related
properties but you must never change its frame, bounds, or alpha
values directly. If you subclass UINavigationBar, you must initialize
your navigation controller using the
initWithNavigationBarClass:toolbarClass: method. To hide or show the
navigation bar, use the navigationBarHidden property or
setNavigationBarHidden:animated: method
https://developer.apple.com/library/ios/documentation/uikit/reference/UINavigationController_Class/Reference/Reference.html
Now I do this and it works perfectly:
1) in entrance point in your view controller add your self as observer to the movies player states
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(playerChangedState) name:#"UIMoviePlayerControllerWillExitFullscreenNotification" object:nil];
2) Responding to the notification:
// run this method on the main thread
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
[self.navigationController setNavigationBarHidden:YES];
[self.navigationController setNavigationBarHidden:NO animated:YES];
Note: This code works on iOS 7, I haven't tested it for older versions of iOS.
For anyone looking for an answer, I fixed it by resetting the navigationController.navigationBar frame's origin to 0,20 as follows:
self.navigationController.navigationBar.frame = CGRectMake(0, 20, self.navigationController.navigationBar.frame.size.width, self.navigationController.navigationBar.frame.size.height);
I had a similar problem and the accepted solution didn't help me - what did help was the answer to this post: Disappearing status bar at the top after MPMoviePlayerController is closed
Basically had to add a delayed call to set [UIApplication sharedApplication].statusBarHidden = NO;
(posted here just incase someone else has this issue)

how to make the view go to top when I hide the status bar

- (void)viewWillAppear:(BOOL)animated {
[[UIApplication sharedApplication] setStatusBarHidden:YES animated:YES];
[navigationController setNavigationBarHidden:YES animated:YES];
}
The above code works perfectly fine and when the view is about to appear, a nice animation begins and after that, both the status bar and navigation bar are hidden.
BUT! My 320x480 view is not moved up to the top (0,0) as I want it to, but it is moved to where the navigation bar was, UNDER the (hidden) status bar. Where the status bar was, is blank, and the bottom of my view is cut off from the window. I find this rather strange because as you can see, I am using a UINavigationController to switch views and I am hiding the navigation bar as well, and the view does move 44px up, compensating the disappearing of the navigation bar. It just doesn't take the height of the status bar into account.
Same problem is on my camera view controller: a view in which camera is opening but view is not from top
Any one have idea how to fix this problem ?
Check out this post. I have done this several times. You should be all set.
How to set the top position = 0 after setStatusBarHidden:Yes?
The Code is:
Just a View:
[self.view setFrame: [self.view bounds]];
A view with a scroll view inside
[self.view setFrame: [self.view bounds]];
[self.theScroller setFrame: [self.view bounds]];
"theScroller is the name of my scrollview

How to prevent the view controllers in a tab bar controller from rotating?

I have a tab bar controller managing 4 tabs. I have subclassed the tab bar controller so that the shouldAutorotateToInterfaceOrientation: method only allows a specific view controller in one of the tabs to rotate. Everything works almost fine: the controllers in the remaining tabs do not rotate. However, when the view controller which is allowed to rotate actually rotates, if the user taps one of the remaining tabs, the corresponding view controller also appear rotated (even though its shouldAutorotateToInterfaceOrientation: method explicitly returns NO).
How do I prevent this from happening?
To be clear, here is an example. Tapping on the tabs 0,1, or 2 and trying to rotate the device, nothing happens (correctly). Tapping on the tab 4 and rotating the device, the view associated to the view controller of tab 4 is rotated (correctly). Now, still holding the iPhone in the rotated landscape orientation and tapping another tab (0,1, or 2) reveal a rotated view (which is not correct and what I am trying to avoid).
This is a commonly reported "bug" - however a good workaround is to force the shouldAutorotateToInterfaceOrientation: selector to be triggered as follows:
- (void)viewDidAppear:(BOOL)animated {
UIWindow *window = [[UIApplication sharedApplication] keyWindow];
UIView *view = [window.subviews objectAtIndex:0];
[view removeFromSuperview];
[window addSubview:view];
}