Change UIViewController self.view frame - objective-c

I am trying to display a viewController xib view with its view displayed under a fixed header banner (0,0,320,44) which is an imageView added on Application window.
This is because I need it to stick on the screen while I navigate multiple view controllers. Its a requirement of the project I am doing.
So far I have tried:
Resizing the XIB view to the appropriate frame size (0,0,320,416), both with dot notation and setter.
Changing the frame in viewDidLoad with self.view.frame = CGRectMake(0, 44, 320, 416);
but it is not working. Any suggestion?

Set the frame in viewWillAppear
- (void)viewWillAppear:(BOOL)animated
{
self.view.frame = CGRectMake(0, 44, 320, 416);
[super viewWillAppear:animated];
}

Just want to add a bit more. The reason for changing view of a UIViewController does not work in viewDidLoad is because of the call [window makeKeyAndVisible], which is usually called after your viewDidLoad. This call will change the frame of the window.rootViewController to equal the window's frame. You can test this by changing the UIViewController's view.frame AFTER [window makeKeyAndVisible], and the changes will stick.
viewWillAppear and viewDidAppear are called within [window makeKeyAndVisible] but after the view's frame got resized.
The caveat is that only the top most controller which is the rootViewController has its view's frame changed automatically. This DOES NOT affect any childViewControllers attached to the rootViewController.

Related

frame of Root ViewController's View when loaded programmatically

Im loading a root view controller in landscape mode at launch(no interface builders are used).
In viewDidLoad, I am adding subviews to root view controllers view, like this
- (void)viewDidLoad
{
[super viewDidLoad];
// self.view.
UIView *toolBar=[[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 50)];
toolBar.backgroundColor=[UIColor darkGrayColor];
[self.view addSubview:toolBar];
//code contiues...
}
but self.view.frame.size.width returns width of portrait mode instead of landscape.
thanks in advance
EDIT:
Implement the -loadView method:
- (void)loadView
{
self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
}
Also normally the parent view controller is responsible for setting the frame size of its children view controllers views. In the case of the root view controller, I believe it takes the size of the UIWindow it's attached to (so if you set the window size in you app delegate, you can just use [[UIView alloc] init] and then set the autoresizing mask in the -loadView method).
You might need to take the status bar into account in the above code, depending on your own code.
may be, portrait orientations are first in your project file (click to project in xcode, info tab in target, unit Supported interface orientations) ? If so, your app can launched in portrait orientation, then send viewDidLoad and rotate to landscape only after this.
When you do not use Interface Builder/xib files and neither create your view manually within loadview, the systems creates one with the maximum dimensions. This is stated in the loadview method documentation:
If the view controller does not have an associated nib file, this
method creates a plain UIView object instead.
This system generated UIView object has a transform property that is not the identiy transformation and thus you are not allowed to rely on the values from the frame property as stated here:
http://developer.apple.com/library/ios/documentation/uikit/reference/UIView_Class/UIView/UIView.html#//apple_ref/occ/instp/UIView/transform
Warning: If this property is not the identity transform, the value of
the frame property is undefined and therefore should be ignored.
So, what should you to instead? I guess the best solution is to use the bounds property of you UIView. This contains the already rotated coordinates.

Why aren't my NSViews in my NSWindow resizing when the window is resized?

I'm pulling my hair out trying to figure why my views aren't resizing with my NSWindow on drag.
Okay, here's my structure:
Subclassed NSWindowController's View (Use Auto Layout Checked for window. Auto Resize checked for view. Window's View not hooked up to anything in IB, should it be?)
Various Buttons
Custom View (Auto Resizes Subviews checked)
Subclassed NSViewController's View (Auto Resizes Subviews & Translates Mask checked)
Various Subviews (Auto Resizes Subviews checked)
Subclassed NSViewController's View (Auto Resizes Subviews & Translates Mask checked)
Various Subviews (Auto Resizes Subviews checked)
I'm adding each of these views to my NSWindowController's Custom View. This is the only relevant method in my file:
-(void)setActiveView:(NSString*) viewString{
if ([currentViewController view] != nil)
[[currentViewController view] removeFromSuperview];
if ([viewString isEqualToString:kFirstView]){
FirstViewController *viewController = [[FirstViewController alloc]initWithNibName:kFirstView bundle:nil];
if (viewController != nil){
currentViewController = viewController;
}
}
else if ([viewString isEqualToString:kSecondView]){
SecondViewController *viewController = [[SecondViewController alloc]initWithNibName:kSecondView bundle:nil];
if (viewController != nil){
currentViewController = viewController;
}
}
//Resize Controller to Window's size.
[[currentViewController view] setFrame:[myWindowView bounds]];
//Embed current view into Custom View in host view.
[myWindowView addSubview:[currentViewController view]];
}
The setFrame to resize does work when I change views, but not when I drag to resize my window. As far as I can tell, because setFrame works when I change views, the only one that really matters (but isn't working) is the Custom View inside my NSWindowController.
Also, this is how I bring this window forward:
myController = [[MyWindowController alloc]initWithWindowNibName:#"MyWindow"];
[myController showWindow:nil];
Yes I've already tried in my initwithframe:
[myWindowView setAutoresizesSubviews:YES];
[myWindowView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
What am I missing?
Try to do this without Auto Layout.
Try this:
Uncheck Use Auto Layout for window.
Go to Size inspector and make autosizing to Your Views like this:

UIViewController present another UIViewController

I Have a UIViewController 1 on it UIButton (added as subview), after I pressed Button (see pic.1 below) on it adding another UIViewController 2 with animation from the bottom to top after some action:
[[[UIApplication sharedApplication] keyWindow] addSubview:self.view];
And it overlaps UIButton, how can I add this subview that it does not cover UIButton(see pic.2 below)
pic.1:
pic. 2:
You haven't shown the animation code but I assume you add the subview off-screen, then change it's frame (animated) to slide it into view.
Add the new subview using insertSubview:belowSubview: instead, passing your button as the second argument. This way the button will overlap the new view, instead of the other way round. addSubview: always puts the new view on top of any others.
EDIT
From your comments it seems that you're adding the second view controller to the screen using presentModalViewController: so the above method won't work. As far as I know there is no way to keep an element from the original view controller on top of the new view controller's view if you are presenting it this way.
You may have to create a new UIWindow and set it's windowLevel to UIWindowLevelAlert to hold your button. This will keep it on top of any of the views underneath. Add this window as a subview to the main window.
{
SecondViewController *objComing=[[SecondViewController alloc] init];
[self.view addSubview:objComing.view];
objComing.view.backgroundColor=[UIColor blueColor];
objComing.view.frame=CGRectMake(0,420, 320, 0);
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
objComing.view.frame=CGRectMake(0,0, 320, 420);
[UIView commitAnimations];
}
Put this code in the button action and replace secondViewController with your ViewController.

presentModalViewController ontop of subview?

I am trying to recreate the iPhone's tabView, but with my own style, buttons, etc. I didn't want to have to totally redo my app, so I simply added a view to the bottom like this [window addSubview:theToolbar]; theToolbar.frame = CGRectMake(0, 425, 320, 44); in my appDelegate.
However, when trying to do this from a view inside a navigationController theToolbar is over it. Is there anyway to somehow present it to the front?
Here's my code to present the view:
AppSettingsController *appSettings = [[AppSettingsController alloc] initWithNibName:nil bundle:nil];
appSettings.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:appSettings animated:YES];
[appSettings release];
Thanks.
it's impossible show partial views of the viewcontroller. if your want to use the same toolbar, you should retain the toolbar to your appdelegate, and add the toolbar to each viewcontroller when it is in view.
or you should just use uiview's as viewcontrollers

Adding a UINavigationController as a subview of UIView

I'm trying to display a UILabel on top of a UINavigationController. The problem is that when I add the UILabel as a subview of UIWindow it will not automatically rotate since it is not a subview of UIViewController (UIViewController automatically handles updating subviews during rotations).
This is the hierarchy I was using:
UIWindow
UILabel
UINavigationController
So I was thinking I could use the following hierarchy:
UIWindow
UIViewController
UIView
UILabel
UINavigationController
This way the label could be displayed on top of the UINavigationController's bar while also automatically being rotated since it is a subview of UIViewController.
The problem is that when I try adding a UINavigationController as a subview of a view:
[myViewController.view addSubview:myNavigationController.view];
it will appear 20 pixels downwards. Which I'm guessing is because it thinks it needs to make room for the status bar. But, since the UINavigationController is being placed inside a UIView which does not overlay on top of the status bar, it is incorrectly adding an additional 20 pixels. In other words, the top of the UINavigationBar is at the screen's 40 pixel mark instead of at 20 pixels.
Is there any easy way to just shift the UINavigationController and all of its elements (e.g. navigation bar, tool bar, root view controller) up 20 pixels? Or to let it know that it shouldn't compensate for a status bar?
If not, I guess I would need to use my first hierarchy mentioned above and figure out how to rotate the label so it is consistent with the navigation bar's rotation. Where can I find more information on how to do this?
Note: by "displaying a label on top of the navigation bar", I mean it should overlay on top of the navigation bar... it can't simply be wrapped in a bar button item and placed as one of the items of the navigation bar.
Using this code seems to work:
nav.view.frame = CGRectMake(nav.view.frame.origin.x, nav.view.frame.origin.y - 20,
nav.view.frame.size.width, nav.view.frame.size.height);
I did this before adding the navigation controller as a subview. Using the [UIApplication sharedApplication].statusBarFrame instead of the hard coded 20 would probably be a good idea too.
I'm not sure if it's the best way to do it though.
If you want a frame representing the available content area, then you should just use: [[UIScreen mainScreen] applicationFrame]. Of course, this restricts your top-level view controller so that it can only be top level. So still kind of dodgy, but less so.
Why don't you use App Frame instead of adding some values to origins? I mean using:
CGRect appFrame = [[UIScreen mainScreen] applicationFrame];
as a reference frame, and do something like this:
nav.view.frame = CGRectMake(appFrame.origin.x, appFrame.origin.y, ...
This one worked for me.
I had this same problem actually but managed to fix it.
I noticed that my view controller's view had the correct frame, but the view controller's navigation bar did not (it had a frame origin of (0,20) ).
Insert this into the view's controller that is the superview of the navigation controller:
- (void) viewDidAppear:(BOOL)animated {
if (navigationController.navigationBar.frame.origin.y != 0) {
[[navigationController view] removeFromSuperview];
[[self view] addSubview:navigationController.view];
}
}
Swift 5:
add the following line in the viewDidLoad() of the root view controller of the UINavigationController.
self.edgesForExtendedLayout = [.top, .bottom]