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.
Related
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.
In my app all my controls are created in code. I have not used IB for controls. now i want to rotate the view to landscape mode. I know I have to use the shouldAutorotate method for this purpose.
But since I have not used IB, how can I resize the controls when they are in landscape mode? How can I position them correctly using code only?
In most cases you can get views to resize themselves appropriately just by setting their autoresizingMask property to some combination of:
UIViewAutoresizingFlexibleLeftMargin
UIViewAutoresizingFlexibleRightMargin
UIViewAutoresizingFlexibleTopMargin
UIViewAutoresizingFlexibleBottomMargin
UIViewAutoresizingFlexibleWidth
UIViewAutoresizingFlexibleHeight
For example, let's say you want a view's width to increase when you rotate it to landscape, you want it to maintain the same margins relative to the top, left, and right sides of the screen, and you want its height to remain the same. This means that out of the six attributes above, only the width and bottom margin should be flexible. The other four attributes are fixed. So you would do:
yourView.autoresizingMask = UIViewAutoResizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin;
In those rare cases when you can't get the views to behave appropriately using their autoresizingMask property, you can wrap them in a custom view and override that view's layoutSubviews method. This method gets called when the view's frame changes due to autorotation, so you can check [[UIApplication sharedApplication] statusBarOrientation] and update the frames of your subviews manually.
You position them correctly using code the same way you likely positioned them in the original orientation, for example by setting their frame.
As for where in code to do this, check out the various orientation change methods of UIViewController that will be called when the device orientation changes. You could, for example, move/resize the controls in the view within willAnimateRotationToInterfaceOrientation:duration:.
Does anyone know if the uinvagitionbar of a uinavigationcontroller can be moved down? I'd like to move it around 200 pixels down to have a logo on top. From my research, I understand that the navigationbar should not be subclassed and there are only two properties that should be changed, it's color and it's visibility. So is this impossible?
I tried moving it's frame, but to no avail.
I've seen other apps do it, but I'm thinking it might be a toolbar? Can the toolbar be repositioned?
Thanks
Just change the size of the frame of the navigations controller's view.
CGRect frame = navigationController.view.frame;
frame.size.height -= 200.0f;
frame.origin.y += 200.0f;
navigationController.view.frame = frame;
You can then add whatever view you'd like to the view or window that contains the navigationController's view.
There a few tricky things to consider if you plan on doing this by presenting a modal view controller, however.
You can hide the self.navigationController and put another navigation bar in the code which will move according to your frame set.
Yes the tool bar can be repositioned. Just take a control in your code and set its frame as per your requirement.
Happy Coding...
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.
Im using a typical situation with UINavigationController, id like to make the navigation bar a bit taller. setting its bounds and frame dont seem to make a difference, im using this code
//set up the navigation
UINavigationController *navigationController = [UINavigationController new];
[navigationController.navigationBar setBarStyle:UIBarStyleBlack];
[navigationController.navigationBar setTintColor:[UIColor purpleColor]];
[navigationController.navigationBar setBounds:CGRectMake(0.0, 0.0, 480.0, 100.0)];
[navigationController.navigationBar setFrame:CGRectMake(0.0, 0.0, 480.0, 100.0)];
but to no avail. any ideas?
I don't think you can change the height of a navigation bar. Except when you add a prompt message... But that's not what you want.
Frame is the visible area of a view. Bounds is the internal area. Usually this has an origin of (0, 0) and is as wide and high as the frame. However, when the content exceeds the visible area (like with a UIScrollView) the bounds can be larger (and the origin different). You rarely see bounds that are smaller than their respective frames.
EDIT: Looking at your code, what is [UINavigationController new] about? You should do [[UINavigationController alloc] init], shouldn't you?
Also, what you are doing is not really subclassing...
At the time of 2009, there is probably no way to change the height of UINavigationController. However, in iOS SDK 4.3, there is a way (hack).
To change the height of UINavigationController, change its frame size in viewWillAppear:animated: function. Then, the height will stay customized throughout whole app.
As far as I know the standard navigation bar height should not be changed.
"Specifically, it is alright to
modify the barStyle, tintColor, and translucent properties, but you
must never directly change UIView-level properties such as the frame,
bounds, alpha, or hidden properties directly."
If you like to customize the appearance of navigation bar you can use the appearance proxy [UINavigationBar appearance] in iOS 5