UIToolbar left and right paddings are initially negative - ios

I'm struggling with UIToolbar's strange behaviour in iOS7+ iPhone application.
Here's how I created it:
//toolbar
self.bottomToolbar=[[UIToolbar alloc] initWithFrame:CGRectMake(0.0, self.view.bounds.size.height-44.0, self.view.bounds.size.width, 44.0)];
self.bottomToolbar.autoresizingMask=(UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth);
[MKUIHelper toolbar:self.bottomToolbar setBarStyle:MKBarStyleWhite];
self.bottomToolbar.items=#[];
[self.view addSubview:self.bottomToolbar];
When I need to update it I'm calling (actually updating only one of its items but this does not matter):
-(void)updateToolbar
{
UIBarButtonItem *doneBarButtonItem=[[UIBarButtonItem alloc] initWithTitle:#"done" style:UIBarButtonItemStylePlain target:self action:#selector(backButtonDidPress:)];
doneBarButtonItem.tintColor=MK_Color_Green;
UIBarButtonItem *clearBarButtonItem=[[UIBarButtonItem alloc] initWithTitle:#"clear" style:UIBarButtonItemStylePlain target:self action:#selector(clearButtonDidPress:)];
clearBarButtonItem.tintColor=MK_Color_Pink;
UIBarButtonItem *spaceBetweenBackAndQuantity=[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *spaceBetweenQuantityAndClear=[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *quantityItem=[self quantityBarButtonItem];
self.bottomToolbar.items=[NSArray arrayWithObjects:doneBarButtonItem, spaceBetweenBackAndQuantity, quantityItem, spaceBetweenQuantityAndClear, clearBarButtonItem, nil];
[self.rootViewController reloadToolbar];
}
Both UIBarButtonItem objects that was created using initWithTitle:.. have negative left and right paddings somehow. It can be roughly fixed by adding additional fixed space type UIBarButtonItems to both sides of the items array. In other words: compensate strange initial left and right paddings with fixed space type UIBarButtonItems.
Help me someone, please. What causes such strange effect? How can I get rid of this strange padding?
Here's how it looks like:

If you set the width of barButtons to correct width, you may be able to work around this.
- (UIBarButtonItem *)barButtonWithTitle:(NSString *)title action:(SEL)action {
UIBarButtonItem *barButtonItem = [[[UIBarButtonItem alloc] initWithTitle:title style:UIBarButtonItemStylePlain target:self action:action] autorelease];
UIButton *button = [UIButton buttonWithType: UIButtonTypeCustom];
[button setTitle:title forState: UIControlStateNormal];
[button sizeToFit];
CGSize size = button.bounds.size;
[barButtonItem setWidth:size.width];
return barButtonItem;
}

Related

move menu button slightly right

I want to have a controller with both back button and menu button as in given image.amazon app
But the problem is the even after increasing the x-axis value it does not shift to right. Hence, I am unable to add back button image. Here's what I am doing right now.
button = [[UIButton alloc] initWithFrame:CGRectMake(200, 100, 100, 25)];
[button setImage:[UIImage imageNamed:#"menu.png"] forState:UIControlStateNormal];
[button addTarget:[SlideNavigationController sharedInstance] action:#selector(toggleLeftMenu) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
[SlideNavigationController sharedInstance].leftBarButtonItem = rightBarButtonItem;
Try this,
UIBarButtonItem *btnBack = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:#selector(back)];
UIBarButtonItem *btnMenu = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:#selector(menu)];
[self.navigationItem setLeftBarButtonItems:[NSArray arrayWithObjects:btnBack, btnMenu, nil]];
Well on your code you specifically replaced the back button with a barBarButtonItem.
BTW, your naming is a bit confusing you are assigning a rightBarButtonItem to the leftBarButtonItem of the navigationController.
[SlideNavigationController sharedInstance].navigationItem.leftBarButtonItems= #[leftButton,menuButton]; // this will assign both button on the left side. same thing for rightBarButtonItems

Programmatically add a back button to a UINavigationBar?

I am using the following code to achieve a navigation bar in my app. (my app was crashing when I used a push segue so I need a modal segue meaning the nav bar is hidden after the modal segue is called)
UINavigationBar *navbar = [[UINavigationBar alloc]initWithFrame:CGRectMake(0, 0, 320, 50)];
//do something like background color, title, etc you self
[self.view addSubview:navbar];
Does any one know any methods I can use with the above code to achieve back button functionality in the nav bar??
Use below code to add back button on left side of navigation bar.Add UIBarButtonItem on Navigation bar.
UIBarButtonItem *backButton = [[UIBarButtonItem alloc]
initWithTitle:#"Back"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(backBtnClicked:)];
self.navigationItem.leftBarButtonItem = backButton;
Use below code to add back button on left side
UINavigationBar *navbar = [[UINavigationBar alloc]initWithFrame:CGRectMake(0, 0, 320, 50)];
//do something like background color, title, etc you self
[self.view addSubview:navbar];
UINavigationItem *item = [[UINavigationItem alloc]
init];
navbar.items= #[item];
UIBarButtonItem *backButton = [[UIBarButtonItem alloc]
initWithTitle:#"Back"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(backBtnClicked:)];
item.leftBarButtonItem = backButton;
BackButton is better than LeftButton I think:
UIBarButtonItem *backBtn = [[UIBarButtonItem alloc] init];
[desVC.navigationItem setBackBarButtonItem:backBtn];
Add Back Button With Image :
UIButton *backButton = [[UIButton alloc] initWithFrame: CGRectMake(0, 0, 70.0f, 21.0f)];
UIImage *backImage = [UIImage imageNamed:#"backBtn"];
[backButton setImage:backImage forState:UIControlStateNormal];
[backButton setTitleEdgeInsets:UIEdgeInsetsMake(10.0, 10.0, 10.0, 0.0)];
[backButton setTitle:#"Back" forState:UIControlStateNormal];
[backButton addTarget:self action:#selector(backButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *backButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
[negativeSpacer setWidth:-15];
self.navigationItem.leftBarButtonItems = [NSArray arrayWithObjects:negativeSpacer,backButtonItem,nil];
Regarding the back button, the proper way is not to create your own.
The UINavigationItem class has proper support for this:
func setHidesBackButton(_:animated:)
var leftItemsSupplementBackButton: Bool
So, if you want to add a custom button on the left side, just set leftItemsSupplementBackButton to true.
Or call
self.navigationItem.setHidesBackButton(false, animated:false)

Spacing between custom type right bar button items

I have four right bar button items added in a navigation bar.
UIButton *replybutton = [UIButton buttonWithType:UIButtonTypeCustom];
[replybutton setImage:[UIImage imageNamed:#"reply.png"] forState:UIControlStateNormal];
[replybutton addTarget:self action:#selector(replyAction:)forControlEvents:UIControlEventTouchUpInside];
[replybutton setFrame:CGRectMake(0, 0, 30, 28)];
UIBarButtonItem *replyBarButton = [[UIBarButtonItem alloc] initWithCustomView:replybutton];
// there are 3 more buttons like this..
self.navigationItem.rightBarButtonItems = [[NSArray alloc] initWithObjects:replyBarButton, replyAllBarButton, forwardBarButton, deleteBarButton, nil];
I want to give some extra spacing between these four bar button custom type items. I tried imageInsets,
replyBarButton.imageInsets = UIEdgeInsetsMake(0.0, 40.0, 0.0, 0.0);
but it doesn't give spacing. Could someone advise me, how can i give extra spacing between four right bar custom type button items?
You can use UIBarButtonSystemItemFlexibleSpace or UIBarButtonSystemItemFixedSpace.
Here is an example:
UIButton *button1 = [UIButton buttonWithType:UIButtonTypeCustom];
[button1 setImage:[UIImage imageNamed:#"icon.png"] forState:UIControlStateNormal];
[button1 addTarget:self action:#selector(replyAction:) forControlEvents:UIControlEventTouchUpInside];
[button1 setFrame:CGRectMake(0, 0, 30, 28)];
// other buttons are created the same way
UIBarButtonItem *item1 = [[UIBarButtonItem alloc] initWithCustomView:button1];
UIBarButtonItem *item2 = [[UIBarButtonItem alloc] initWithCustomView:button2];
UIBarButtonItem *item3 = [[UIBarButtonItem alloc] initWithCustomView:button3];
UIBarButtonItem *item4 = [[UIBarButtonItem alloc] initWithCustomView:button4];
UIBarButtonItem *space1 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *space2 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *space3 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
self.navigationItem.rightBarButtonItems = #[item1, space1, item2, space2, item3, space3, item4];
In this example, you are adding flexible spaces between every item. This will automatically space your items evenly.
If you want, you can also define the space:
UIBarButtonItem *fixedSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
fixedSpace.width = 40.0 // adjust this

UIToolBar with UIBarButtonItems equally spaced regardless of title length

So I'm tasked with adding buttons to a UIToolBar and setting the inputAccessoryView of a textView to this UIToolBar.
so I did the basics:
UIBarButtonItem *item1 = [[UIBarButtonItem alloc] initWithTitle:#"title1" style:UIBarButtonItemStylePlain target:self action:selector];
UIBarButtonItem *item2 = [[UIBarButtonItem alloc] initWithTitle:#"longer title2" style:UIBarButtonItemStylePlain target:self action:selector];
UIBarButtonItem *item3 = [[UIBarButtonItem alloc] initWithTitle:#"title 3 is a lot longer" style:UIBarButtonItemStylePlain target:self action:selector];
UIBarButtonItem *spacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *divider1 = [self barButtonDivider];
UIBarButtonItem *divider2 = [self barButtonDivider];
UIToolBar *toolBar = [UIToolBar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 44)];
[toolBar setItems:#[spacer,item1,spacer,divider1,spacer,item2,spacer,divider2,spacer,item3,spacer];
self.textView.inputAccessoryView = toolbar;
So there are more approaches to this.
1) I could subclass a UIToolBar
2) I could subclass a UIView and set a view to be the size I need (width of the superView and height 44), but I'd need to do all of this in Auto-Layout which I tried and could not get right.
Is there a way I can use the above method with a standard ToolBar and get the right spacing where all the buttons no matter how many I use are equal widths?
ETA:, tried the below solution and didn't work:
- (UIBarButtonItem *)spacer {
return [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
}
[toolBar setItems:#[[self spacer], item1, [self spacer], divider1, [self spacer], item2, [self spacer], divider2, [self spacer], item3, [self spacer]];
Resolved with this solution but I don't like it:
button.width = 150;
the buttons would remain equal in portrait or landscape so I guess this is a working solution what do you think?
I'm not sure, but issue might be in reusing spacer. Try to create new UIBarButtonSystemItemFlexibleSpace every time you need flexible space.

LeftBarButtonItem with two buttons. One Button doesnt respond to tap

So I have two buttons in the leftBarButtonItem. This is my code.
NSString *todayString = #"...";
UIBarButtonItem *todayButton = [[[UIBarButtonItem alloc] initWithTitle:todayString style:UIBarButtonItemStyleBordered target:self.calendarController action:#selector(todaySelected)] autorelease];
NSString *weeklyString = #"...";
UIBarButtonItem *weeklyButton = [[[UIBarButtonItem alloc] initWithTitle:weeklyString style:UIBarButtonItemStyleBordered target:self action:#selector(weekSelected)] autorelease];
UIToolbar *toolbar = [[[UIToolbar alloc] init] autorelease];
[toolbar setItems:[NSArray arrayWithObjects:todayButton, weeklyButton, nil]];
self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithCustomView:toolbar] autorelease];
The title of the buttons is dynamic. Sometimes the titles can get somewhat long. The buttons expand and look fine. However, if the titles get too long, it seems that the UIToolbar reaches some width maximum, as the buttons stop responding to taps at a certain X point. See image here
Green represents responds to touch and red does not respond to touch. The Today button responds to touch. The Weekly button, however, only responds to touch until the second "e". Anything after that does not respond to touch.
I've been banging my head trying to fix this for a while, with no luck. I tried expanding the frame of both the UIToolbar and the leftBarButtonItem. Anyone know whats going on? Thanks in advance
Your toolbar frame width is probably too narrow. In your code, you don't even set its size, and rely on it to be sized it for you. Trying setting it to larger width, and make sure the autoresizingMask does not have `UIViewAutoresizingFlexibleWidth' set.
A good debugging technique is to set the background color of your new toolbar to something bright (to contrast against the toolbar you are installing it into) and watch its sizing to see how your button is being clipped interaction-wise.
You may need to explicitly resize it as you update the bar button item titles if fixing it to a certain width is too restrictive for your app.
You'll need to make a custom button view that is actionable, with something like a UIButton:
UIButton *newButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[newButton addTarget:self action:#selector(newAction:) forControlEvents:UIControlEventTouchUpInside];
[newButton setTitle:#"New Button" forState:UIControlStateNormal];
UIBarButtonItem *newBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:newButton];
self.navigationItem.leftBarButtonItem = newBarButtonItem;
for example.
EDIT - now I see what you are doing, I apologize for the earlier confusion. You are adding an array of buttons to the left side. Try adjusting the frame of the toolbar with so the buttons fit inside the interactive area:
NSString *todayString = #"...";
UIBarButtonItem *todayButton = [[UIBarButtonItem alloc] initWithTitle:todayString style:UIBarButtonItemStyleBordered target:self action:nil];
NSString *weeklyString = #"...";
UIBarButtonItem *weeklyButton = [[UIBarButtonItem alloc] initWithTitle:weeklyString style:UIBarButtonItemStyleBordered target:self action:nil];
UIToolbar *toolbar = [[UIToolbar alloc] init];
[toolbar setFrame:CGRectMake(0, 0, 320, 50)];
[toolbar setItems:[NSArray arrayWithObjects:todayButton, weeklyButton, nil]];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:toolbar];
I know this is an old question, but it led me astray for a bit until I found updated information. I could not use the technique mentioned above in iOS 7 because the embedded toolbar would not line up with its parent.
Anyhow, iOS 5 (I believe) added button arrays for the left and right items:
UIBarButtonItem * trashItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemTrash target:self action:#selector(onTrashClick:)];
UIBarButtonItem * mailItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:#selector(onActionClick:)];
self.navigationItem.rightBarButtonItems = [[NSArray alloc] initWithObjects: refreshBtn, selectYearBtn, nil];

Resources