UIToolbar height on device rotation - iphone

From the iOS Human Interface Guidelines, iOS UI Element Usage Guidelines
On iPhone, take into account the
automatic change in toolbar height
that occurs on device rotation. In
particular, make sure your custom
toolbar icons fit well in the thinner
bar that appears in landscape
orientation. Don’t specify the height
of a toolbar programmatically.
I can see the height changing from 44 points to 32 points in Mail, Twitter for iPhone and Dropbox for example, but when I add a toolbar (with Interface Builder) and have my UIViewController subclass to automatically rotate (shouldAutorotateToInterfaceOrientation: returns YES), the toolbar does not automatically change its height on device rotation.
The UIToolbar Class Reference does not mention this automatic change of height, so am I supposed to change it programmatically even though the HIG says Don’t specify the height of a toolbar programmatically?

Did you check the auto-resizing property of the toolbar?

As noted by yonel and George in the comments from 7KV7 answer, changing the autoresizing mask does not work as intended on iOS 5.
I found another solution by using the -[UIView sizeThatFits:] method. Here is how I did it:
- (void) layoutForInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Adjust the toolbar height depending on the screen orientation
CGSize toolbarSize = [self.toolbar sizeThatFits:self.view.bounds.size];
self.toolbar.frame = (CGRect){CGPointMake(0.f, CGRectGetHeight(self.view.bounds) - toolbarSize.height), toolbarSize};
self.webView.frame = (CGRect){CGPointZero, CGSizeMake(CGRectGetWidth(self.view.bounds), CGRectGetMinY(self.toolbar.frame))};
}
Then I call this layoutForInterfaceOrientation: method in my view controller viewWillAppear: and willAnimateRotationToInterfaceOrientation:duration: methods.
The height is nonetheless changed programmatically but at least the value is not hardcoded.

This behavior is a lot simpler to achieve with auto layout. I've only tested in iOS8 but the following code works for me with the desired animation on orientation change:
public override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
toolbar.invalidateIntrinsicContentSize()
}

If you use a ViewController inside a NavigationController, you can use the NavigationController’s toolbar instead of creating your own, and let it handle the resizing. This is what the ViewController's toolbarItems property is for, actually.

Related

Why is self.bounds.size.height not taking into account the UINavigationView nav bar in this code?

I have a configuration UITableView that can launch a colour picker via a UINavigationController approach:
[self.navigationController pushViewController:colorPickerViewController animated:YES];
[colorPickerViewController release];
The effect of this means the ColourPicker will have a navigation bar at the top ( and back button)
The structure of the ColourPickerViewControll and it view ColourPickerView is as follows:
- ColourPickerViewController - in it's XIB file at the top level view it has:
- ColorPickerView : UIView (i.e. custom UI view) - in it's methods it has:
- (id)initWithCoder:(NSCoder*)coder {
if ((self = [super initWithCoder:coder])) {
CGFloat currVertBounds = self.bounds.size.height;
The issue here is the the value of currVertBounds is coming to 480, so it's not taking account of the navigation bar
QUESTION: How do I get the true displayed height of the ColorPickerView instance?
Is it something to do with trying to get the layout calculated in the custom UIView, and perhaps the custom view isn't rendered within the overall controll/navigationController at that stage?
You're reading bounds too early. None of the layout/subviewing magic that happens in UIKit will take place during [super initWithCoder:]. You should be reading bounds and laying out your view either:
In viewDidLoad/viewWillAppear, and set up the autosizing parameters for all manually created UI elements so they can get moved around with respect to different interface orientations. In these functions I wouldn't rely on bounds being exactly correct but I would say it's at least the right height:width ratio. It could possibly be in the wrong orientation, though.
In viewDidAppear, if you wish to manually position elements. By the time you hit viewDidAppear all of the resizing and such has taken place, and the only thing left to worry about is future rotations, which you should adjust your view for in willAnimateRotationToInterfaceOrientation:duration:.
Docs on willAnimateRotationToInterfaceOrientation:duration: state:
By the time this method is called, the interfaceOrientation property is already set to the new orientation. Thus, you can perform any additional layout required by your views in this method.
iOS 5.0 docs add the clause:
...set to the new orientation , and the bounds of the view have been changed. Thus...
I think this is still the case for prior iOS versions.
Views for iPhone will by definition have a height of 480 pixel when created in Interface Builder, so that's what you're seeing when you're initializing the view. Once the view has been properly initialized and added to the view stack, it will be resized to match the actual space available.
You're simply asking the view of its height before it has been adjusted.
Try reading the height in viewDidLoad, then it should be correct.
Yes, this is right because the instance of UINavigationController is declared in your (delegate.h) & that navigationBar is added to window not on your self.view
When you check the bounds of your current view, it should definitely return 320 * 480.
It should not include height of navigation bar in you view, as it not on that view. Its on window.

iOS: Is is possible to make a UINavigationBar taller and "push" the other views down the screen?

Is there a way to make the "content" area of an iPhone app aware of a larger navigation bar?
Similar to these questions:
iOS: Adding a fixed image just below the navigation bar
iOS: Positioning navigation bar buttons within custom navigation bar
I've managed to use the 1st questions sample code to add a category on UINavigationBar and change its height, and added a subview where I need it, but I can't see a way to cause the UITableView (or indeed any content views) to take its height into consideration:
(The colors are only to make the different views distinguishable)
The accepted answer to the first question sets the nav bar's frame in -layoutSubviews, which is anywhere from "ewwwww" to outright wrong depending on the assumptions made by other layout code.
Instead, override -sizeThatFits: to return a more appropriate size.
I'd go about this by adjusting the tableView.frame, so something like this:
CGRect navFrame = self.navigationController.navigationBar.frame;
CGRect tableFrame = self.tableView.frame;
tableFrame.size.height = tableFrame.size.height - navFrame.size.height;
tableFrame.origin.y = navFrame.size.height; //move it down by the height covered by the navigation Bar
self.tableView.frame = tableFrame;
You could do this with your other views as well - i.e. by simply adjusting the frame.
I've not got XCode on this computer, so I've not checked the code - just written it out as an example, so please check it yourself before using it!

Where do I change the height of a navigationBar for an iPhone app?

In my applicationDidFinishLaunching I set up a UINavigationController:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
navController = [[UINavigationController alloc] init];
[[navController navigationBar] setFrame:CGRectMake(0.0,0.0,320.0,20.0)];
...
}
As you can see, I am trying to make the navigation controller's height 20px. However, this is not working. I would imagine setFrame must be the correct function but I am not calling it in the right place. I realize that other questions on SO are similar to mine, but I think setting the navigationBar height should be possible if it responds to setFrame...right?
Also, anyone know the default height of the navigationBar?
Thanks!
The default height of the navigation bar is 44px.
I am not sure you should be attempting to directly resize the navigation bar, the documentation certainly discourages it:
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 of this class,
but you must never directly change
UIView-level properties such as the
frame, bounds, alpha, or hidden
properties directly.
Depending on what you are trying to do it may be easier to place a new UIView over/below the navigation bar.
Default height is 44 pixels for navigationbar.
If you want to change it, try adding a category to UINavigationBar and override setFrame: method.

Iphone - UIToolbar automatic position

I have an application where a UIToolBar is to be constantly on the bottom side of the screen. No matter the device orientation.
The toolbar must have the same screen width and always be justified to the bottom side.
If the device rotates, the toolbar has to assume the new width and continue to be justified on the bottom.
Is there a way to do that programmatically?
thanks for any help.
First off, auto-rotation can be a little tricky. For example, if you are using a UITabBarController, you will need to subclass it and add the appropriate delegate methods. You should read up on auto-rotation via the Apple docs and Google, before really diving in.
To answer your question specifically though, here is how you would need to declare the UIToolbar such that it will auto-rotate when you have the app set up to do so:
// I keep this definition in a file called constants.h since I use it a lot
#define SCREEN_FRAME [[UIScreen mainScreen] applicationFrame]
UIToolbar *tb = [[[UIToolbar alloc]init]autorelease];
// this frame will position a toolbar at the bottom of the screen
tb.frame = CGRectMake(0,
SCREEN_FRAME.size.height-tb.frame.size.height,
SCREEN_FRAME.size.width,
tb.frame.size.height);
//Setting the auto-resizing mask will make the toolbar resize when the viewController
//it resides in rotates.
tb.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
Yes. Have a look at autoresizing masks.
Use a navigation controller, and make use of the toolbarItems property.

Resizing UITableView on RootController

Is it possible to resize the UITableView on the RootController of a nav based app? When RootViewController.xib is opened in IB, there isn't a view. Just the UITableView. Clicking the inspector and then the little yellow ruler, frame height is grayed out. I'm adding a toolbar programmatically to the RootViewController:
[toolbar setFrame:rectArea];
That works fine but the bottom cell in the tableview is partially hidden because the tableview doesn't know about the toolbar.
The easiest way, is to adjust the contentInset (which is inherited from UIScrollView). Resizing by setting the frame can cause crazy drawing bugs in cells.
For example, if you are trying to resize a tableview for the keyboard, do something like this:
tableView.contentInset = UIEdgeInsetsMake(0.0, 0.0, 216.0, 0.0);
tableView.scrollIndicatorInsets = tableView.contentInset;
Hope that helps someone. This way worked best for me.
Yes, but you need to have a ViewController (not a UITableViewController) as the root controller for the nav, and wrap the actual UITableView in the UIViewControllers view.
You can still have the UIViewController conform to the UITableViewDelgate and Datasource protocols, and use all the same methods you have now in your UITableViewController.
P.S. you'll get more responses if you use the plain "iphone" tag.
You could also just set the Content and Scroller inset of the tableview
I encountered a similar issue when attempting to display the detail controller by itself, see: http://vimeo.com/13054813
The issue is that the SplitView controller applies its own transform to the sub-controllers, taking them out of the orientation detection loop, which blows goats and seems incredibly 'hackish' for built-in classes. (The video illustrates what happens when you make the detail view the root view, then add it back to the split view and make the split view root while in landscape; you get double rotation of the detail view.)
Unfortunately I've again run into these transformation issues while attempting to resize a SplitViewController's detail sub-view in response to the keyboard appearing/disappearing. In portrait, all works fine, in landscape it's fscked.
Yes, adjust the contentInset and scrollIndicatorInsets are the convenient way to resize the UITableView.
As the answer of Sam Soffes posted, I succeed resize UITableView in UITableViewController for the bottom UIToolbar.