3

With regards to designing your own view Controller by inserting a UINavigationBar into the scene, I have found many references to questions regarding how the frame height does not change when rotating the device. This is in contrast to how Apple utilizes the UINavigationBar within it's navigation controller where the height of the bar does change upon rotation.

While there have been suggestions which do in fact show how to change the height to be consistent with what Apple does, all the answers do not address proper relationships to other views in the scene. In particular, when constructing a scene that utilizes autoLayout, you should never have to adjust the frame - auto layout is suppose to take care of this for you through the constraints you define.

For example, one suggestion was to do this:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 
{
    [self.navigationBar performSelector:@selector(sizeToFit) withObject:nil afterDelay:(0.5f * duration)];
}

While this will change the size, the relationship to other views is no longer correct. Although the poster in the above example did provide a solution to account for adjusting the relationship, this was more of a hard-coded approach, not one Apple likely suggests, i.e. not an autoLayout-friendly solution.

Through experimentation, I noticed that when rotating the device, the intrinsicContentSize did in fact change properly, but the frame did not. In noticing this, I tried the following:

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];

    CGRect frame = self.navigationBar.frame;
    frame.size.height = self.navigationBar.intrinsicContentSize.height;
    self.navigationBar.frame = frame;
}

While this did properly change the size, like the above example, it too resulted in incorrect view relationships.

Specifically, my device in landscape:

enter image description here

Then switching to portrait:

enter image description here

Is anyone aware of how Apple wants us to address UINavigationBar layout using constraints?

Community
  • 1
  • 1
zinc1oxide
  • 490
  • 3
  • 15

1 Answers1

1

Just make a vertical spacing constraint between your button and the top layout guide. This can be done in IB by control dragging from the button to the bottom of the navigation bar. Very simple, no code necessary.

After Edit: If you add a stand alone navigation bar, you do need some code (as far as I know) to get the behavior you get automatically with a navigation controller. The way I did this is to add a navigation bar, and give it constraints to the sides of the superview, a vertical constraint to the top layout guide, and a fixed height of 44 points. I made an IBOutlet to this constraint (called heightCon in the code below). The button has a centerX constraint and a vertical spacing constraint to the navigation bar.

- (void)viewWillLayoutSubviews {
    self.heightCon.constant = (self.view.bounds.size.height > self.view.bounds.size.width)? 44 : 32;
}
rdelmar
  • 103,982
  • 12
  • 207
  • 218
  • Yes, this suggestion will help with the above example. However, code is necessary because the height of the navigation bar needs to be adjusted - which was really the point of the post. Also, the goal is to keep the space between the button and bar when the bar size changes. – zinc1oxide Oct 24 '13 at 23:19
  • @zinc1oxide, It looks like he's talking about the height change you get automatically on rotation of an iPhone -- no code is necessary for that. – rdelmar Oct 24 '13 at 23:26
  • There is no automatic height change when you rotate. In the above suggestion, changing the button constraint does not affect the height of the navigation bar upon rotation. If you know of a way to change the height by defining a constraint, that would be ideal. – zinc1oxide Oct 25 '13 at 00:33
  • @zinc1oxide, I don't know what you're seeing, but on my phone and my simulator (version 7.0) the navigation bar is 44 points high in portrait and 32 points high in landscape -- that happens automatically, and is the normal behavior of a navigation bar on an iPhone. – rdelmar Oct 25 '13 at 03:23
  • I probably should have clarified that if you design your own interface within IB by placing a navigation bar in the scene, you will see this behavior. If I were to place a controller within a navigation, Apple does the work of inserting the navigationBar which does change size upon rotation. This is not what I'm referring to and likely what you are talking about. I've update the original post to clarify. – zinc1oxide Oct 25 '13 at 13:11
  • 1
    @zinc1oxide, Ok, I thick I get what you're doing now. I've updated my answer. – rdelmar Oct 25 '13 at 16:33
  • Thanks rdelmar. I was able to get the exact behaviour based on your updated answer. I did however change the code slightly in my version to avoid hard-coding constants. Specifically: self.heightCon.constant = self.navigationBar.intrinsicContentSize.height; Note: no other code was necessary to make this work. – zinc1oxide Oct 25 '13 at 21:45