Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Explain this margin logic for leftBarButtonItem, rightBarButtonItem, titleView

Can anyone explain to me where the margins you see in this screen shot below are coming from? I want the red, green and blue rectangles to all fit next to each other in both screen layouts, landscape and portrait. Instead I see inexplicable margins between the views.

// Setup Left Bar Button item
UIBlankToolbar* tools = [[[UIBlankToolbar alloc] initWithFrame:CGRectMake(0, 0, 115, 44)] autorelease];
tools.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[tools setBackgroundColor:[UIColor greenColor]];
self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithCustomView:tools] autorelease];

...

// Setup Right Bar Button Item
UIBlankToolbar* tools = [[[UIBlankToolbar alloc] initWithFrame:CGRectMake(0, 0, 100, 44)] autorelease];
[tools setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
[tools setBackgroundColor:[UIColor redColor]];
self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithCustomView:tools] autorelease];

...

// Setup Title View
self.navigationItem.titleView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 44)] autorelease];
self.navigationItem.titleView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[self.navigationItem.titleView setBackgroundColor:[UIColor blueColor]];

What I see with this code:

enter image description hereenter image description here

What really perplexes me is that the margins between views become BIGGER as the space available becomes smaller? I don't understand why they are there, nor why they behave counter to what I expect from margins.

Thanks!

like image 743
esilver Avatar asked Oct 11 '22 22:10

esilver


1 Answers

The navigation bar has minimum margins between its items that it enforces and that's why you can't get rid of the margins.

Explaining your specific code is not very hard either: 115+100+50 = 265 and the width of the screen is 320, so the navigation bar has 55 pixels to use as margins. The left item is left aligned, the right item is right aligned and the middle item is centered. So the margins you get in portrait makes perfect sense.

What you're seeing in landscape is due to your flexible width. You're not supposed to have flexible width on items in a navigation bar, so the behavior when doing that is undefined, i.e., the bug is in how you use the navigation bar and not in the navigation bar itself.

What's happening is that the new size for the right item is calculated first. It grows from 100 to 100+(480-320) = 260. Then the middle item's size is calculated and it seems like it just takes all the size available to it. When it's time for the left item to be calculated it actually shrinks since the right and middle item has taken all the space, so when the navigation bar enforces the margins the pixels are taken from the left item.

The actual algorithm may differ. After all it's closed source and I'm trying to explain undefined behavior, but looking at the produced margins that seems to be what's happening.

Anyway, you're app should never rely on undefined behavior, as undefined behavior may change between versions and break it. What you should do is create your own custom view and add it as a subview of the navigation bar. Then you'll handle margins within your view the way you want to.

yourView = [[YourView alloc] initWithFrame:(UIInterfaceOrientationIsPortrait(interfaceOrientation)) ? CGRectMake(0, 0, 320, 44) : CGRectMake(0, 0, 480, 44)];
yourView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[self.navigationController.navigationBar addSubview:yourView];
like image 114
Erik B Avatar answered Oct 24 '22 16:10

Erik B