UIToolbarPosition set to bottom on resize - ios

I have a UIToolBar at the top of one of my views and the shadowing shows up on the bottom of the tool bar as I'd expect. I know UIToolbarPosition is internally set to UIToolbarPositionTop.
When I rotate my device (iPad), the tool bar grows (using auto sizing in IB) and the UIToolbarPosition changes to UIToolbarPositionBottom which flips the shadow to be at the top of the bar. If I don't have the bar resize, it remains correct, but of course doesn't stretch to match screen width.
So, what gives? What would cause the UIToolbarPosition to flip on me? This is sitting at 0,0 the whole time and only changes width based on rotation.
Extra: I've considered work arounds like using a UINavigationBar. UIAppearance is probably a no go because I do have a toolbar at the bottom too and I do want my "top" different than my "bottom"

I eventually solved this using the UIBarPositioning protocol on UIToolBarand setting the barPosition = UIBarPositionTop

Related

Positioning a UISegmentedControl in a button bar

I'm trying to use a UISegmentedControl as a custom right button bar item. Using Interface Builder, when I drag the control into the navigation bar, it gets sized to be quite wide (too wide, considering the segment contents):
I've tried setting the widths of the segments to something that I think looks good and the overall control resizes, but it is pinned to the left side of the original space it was allocated. I can't seem to find a way of moving it from there. Here's a picture of what this looks like in IB in landscape:
and here's what it looks like running on an iPhone 7 Plus simulator in portrait mode:
As you can see, the segmented control is positioned way too far toward the center.
I tried a hack (suggested in this thread) of embedding the segmented control inside another view, leaving the containing view to be full width of the bar button item and constraining the segmented view to be on the right of it's container. That gets it over to the right, but here's the effect of running that on an iPhone 7 simulator (somewhat narrower than the 7 Plus):
Here the problem is that the title, which is supposed to be centered, has been pushed off to the left. I assume that this is because the (transparent) bar button item is taking up so much more width than what is needed just for the segmented control.
Is there some way of getting the right button area of the navigation bar to simply be smaller?
My steps are below:
1.Drag the segment control to navigationbar:
2.Change the segment width:
3.iPhone7 & iPhone 7Plus all looks good:

Clear background for status bar in iOS

How can I set the colour of the status bar to be clear. No matter what I do, it is white with some alpha.
I do not want it to disappear and I want the text to be black.
In the picture it might look like nag bar and status bar are grey but actually both are white with some blur affect or nag bar has blur affect and status bar is clear.
Here is what I get despite the clear status bar background colour
The status bar has no background since iOS 7. In other words, it's clear by default.
If you see it white, it means the underlying view is white, and you need to change that.
I was having the same problem. It ended up that my view was constrained to the top layout guide when instead it should have been constrained to the superview. Even though the view is constrained to different points it will look the same in interface builder (in my case, I think this is because I was instantiating the viewcontroller to my navigation controller in code and not displaying the navbar). See the image below.
Click on the constraints for the imageview in the view above and the difference in constraints can be seen in the size inspector.
Constraining to the superview will look like this:
This results in the simulator displaying the view like this:
Notice how the status bar is clear and overlaid on top of the imageview.
Constraining to the top layout guide will look like this:
This results in the simulator displaying the view like this:
Notice how the status bar appears white and how the imageview seems constrained to the status bar (the status bar is white text on a white background fyi).
So, in order to fix this problem, you need to change the constraint of the image view to be constrained to the superview.
You change this by selecting the constraint in this list:
Once you have the constraint selected you can change what the constraint is attached to over here:

Applying bar metrics on a standalone UINavigationBar

My app has a view controller that due to the fact it plays its own custom transition animations, provides its own standalone UINavigationBar view at the top (As opposed to using a UINavigationController).
When using an iPhone, and when rotating the device, I would like the UINavigationBar to automatically apply the landscape UIBarMetrics properties (eg, change height, change the background image, resize the buttons etc), but by default, it does not. This is a problem on iOS 7, since even if I manually change the height of the UINavigationBar, the UIBarButtonItem elements don't change their vertical positions.
Is there a way to manually 'tell' the UINavigationBar to apply specific bar metric properties to itself? Or is that actually an implementation inside UINavigationController, and not UINavigationBar?
After various testing and trial and error after asking this question, I eventually worked out a solution that fixed all of my issues, so I'll post it here under the solution I'd previously accepted.
When my app is displayed in landscape on an iPhone, I wanted the UINavigationBar at the top to shrink to the standardly accepted 32 points high, as is the case with any apps that use the UINavigationController class. However, as I am not using a UINavigationController for this particular view (for varying reasons of feasibility), I needed to implement this manually.
To account for the new transparent status bar in iOS 7, I adjusted the origin and size of the UINavigationBar so it encompassed both the bounds of the status bar, and the normal UINavigationBar region (ie, so the UINavigationBar frame origin was {0,0}, and the height was 52 points.)
Unfortunately, this happened:
While the bar itself is rendering at the proper position and height, all of the content in the bar, including the title and buttons are not positioned properly, being much too high, almost touching the status bar content.
It was pretty obvious what was happening. The navigation bar content is being vertically aligned to its own middle, completely disregarding the presence of the status bar content.
When I tested the same orientations with a normal UINavigationController, this was not the case, and the title and buttons in the UINavigationBar from the UINavigationController worked absolutely fine. Apple had done SOMETHING in there that wasn't part of the normal UINavigationBar implementation.
Going on this, I picked apart the view layout hierarchy of a UINavigationControllerto see what was happening to the UINavigationBar in there (Mainly calling a lot of NSLog() statements that would dump the subviews of the navigation bar.)
This is what I discovered:
From the looks of it, Apple have employed a relatively sneaky hack to achieve this effect. It turns out the actual UINavigationBar is actually placed right below the status bar (ie at point {0,20}) and only has a height of 32 points. Then, what happens is a private subview inside the UINavigationBar in charge of rendering the background is extended upwards, outside of the bounds of the navigation bar to encompass the region behind the status bar (ie, its origin is {0, -20}, and its height is 52 points, local to the navigation bar's subview coordinate space).
So by doing that, not only does the content vertically align properly, but the translucent effect still extends behind the status bar.
Anyway, after I discovered this, it was pretty straightforward to write a solution. All I needed to do was reposition and resize the UINavigationBar back to how I had it iOS 6 (ie, 20 points down, and only 32 points high), and then implement a UINavigationBar subclass that override the layoutSubviews method, grabbed the internal background view (Doing a quick subview check for a view with a class name that matched "Background"), and then manually extended it.
The bar metrics properties you can set on a UINavigation bar are things like background image and the title vertical position. Heigh and width need to be set from within your view controller.
If you need to manually tell the navigation bar to change it's size when the orientation changes you can implement the method - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration1 in your view controller and change the size there.
Another option you can use is to use autolayout to specify that the width of your navigation bar is pinned to the left and right sides of its superview and let it figure out how wide it should be. For example
UINavigationBar *bar = [[UINavigationBar alloc] init];
bar.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:bar];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[bar]|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(bar)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[bar(44)]|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(bar)]];

Simple Horizontal Button Bar for iOS

I have a requirement for a very simple Button Bar.
It should take up the width of the screen.
It should allow at least 3
buttons.
The buttons should be of equal width and together take up
the whole width of the bar.
Each button should be tappable, but not
have a selected state.
The bar will be overlaid on a MapView and positioned directly above a TabBar.
Tapping a button will launch a Modal ViewController.
I thought about using a UITabBar and not allowing its tabs to become selected, but the HIG is pretty clear that this is not correct usage and UIToolBar doesn't allow the button widths to be set.
This seems like a very simple requirement but I can't see an obvious solution. Is there something I'm missing? Can anyone suggest a solution?
What's wrong with just creating a simple view that draws an appropriate gradient, and then adding three buttons of the appropriate size?
If you're feeling ambitious, or if this is something that you're likely to use more than once, you could even have the view create the three buttons. Call it ThreeButtonBar or something. Give it a constant height and adjust the width to match that of its superview so that you can use it in portrait or landscape orientation.

iPad Toolbar UI Question

I need to have an iPad app that has a consistent toolbar at the top of the screen. I need it to adjust when switch from landscape to portrait. Essentially what I need is something that acts like a UINavigationController, but allows me to have an arbitrary number of buttons like a UIToolbar. I've seen this done, but I can't figure out how to do it.
Thanks
There is no reason you can't just use a standard UIToolbar at the top of the screen, rather than the bottom. This allows you to add as many buttons as you can squeeze on, and customise their appearance.
In order that it should adjust its size when switching interface orientation, you simply need to adjust its autoresizingMask property. This is easy in Interface Builder - just turn on the horizontal arrow in the middle of the autoresizing box (this makes the width flexible), and maybe make sure that the left, right and top struts are enabled to so as to hold it in the correct position.

Resources