iOS 7 BarButtonItem with image and title
Asked Answered
U

4

15

I'm trying to figure out how can I achieve something like this:

enter image description here

This is a toolbar and I'd like to keep the button title text without having to create the whole image with icon AND text. How can I add the icon to the left of the UIBarButtonItem while keeping the text set with:

UIBarButtonItem *customBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Button" style:UIBarButtonItemStyleBordered target:nil action:nil];

EDIT

This is what I achieved with the following code:

    UIButton *customButton = [UIButton buttonWithType:UIButtonTypeCustom];
    [customButton setImage:[UIImage imageNamed:@"Test"] forState:UIControlStateNormal];
    [customButton setTitle:@"Button" forState:UIControlStateNormal];
    customButton.titleEdgeInsets = UIEdgeInsetsMake(0, 5, 0, 0);
    [customButton sizeToFit];
    UIBarButtonItem *customBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:customButton];

enter image description here

Two issues here: the first is the size of the UIButton and the second is that, as you can see from the gif, the button doesn't animate properly when I tap inside the button and when I release the tap. Any ideas?

Utopianism answered 5/10, 2013 at 16:40 Comment(3)
You can't just use an ASCII 'up arrow' character?Radiogram
@Undo, that was just an example icon.Utopianism
Possible duplicate of How to have a UIBarButtonItem with both image and textMccombs
B
33

You can embed a UIButton as a custom view inside your UIBarButtonItem. You can create your UIButton however you want, including with an image and text, using -setImage:forState: and -setTitle:forState:.

UIButton* customButton = [UIButton buttonWithType:UIButtonTypeCustom];
[customButton setImage:[UIImage imageNamed:@"image"] forState:UIControlStateNormal];
[customButton setTitle:@"Button" forState:UIControlStateNormal];
[customButton sizeToFit];
UIBarButtonItem* customBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:customButton];
self.navigationItem.leftBarButtonItem = customBarButtonItem; // or self.navigationItem.rightBarButtonItem

Note that when doing this, you'll need to attach your IBAction methods to customButton, not to customBarButtonItem.

For more info, see the documentation for initWithCustomView:.

You can also do all of this in interface builder just by dragging a UIButton to the left bar button/right bar button slot on a navigation bar.

Bloodstain answered 5/10, 2013 at 17:16 Comment(14)
Greg, if I embed a UIButton inside UIBarButtonItem I need to set the UIButton's frame and I won't because I use AutoLayout. Besides this if I use that way the button doesn't 'fade' (animate) when I tap it.Utopianism
@FredCollins, it should fade when you tap it (I just tested). You'll have to set your title colour for state, etc., just like you would any other button.Bloodstain
It fades the text but not the icon image. Does it works to you?Utopianism
I added an example of how to create the custom button without needing to explicitly set the frame.Bloodstain
Yes, it's fading the icon image for me. I updated my answer with the code that I'm using.Bloodstain
Thanks, I'm going to try that. What about to put the icon image to the left?Utopianism
Using the code in my answer, the image should automatically appear to the left. You can adjust the titleEdgeInsets and imageEdgeInsets properties of the UIButton to adjust where the title/image appear.Bloodstain
Greg I've just tried and it doesn't works properly. I mean that when I tap it the whole button doesn't fade like a standard UIBarButtonItem.Utopianism
Did you try setTitleColor:forState:? Set one color for normal, another for highlighted.Bloodstain
Greg, it seems that a solution is to create the whole image (icon+text) and use [[UIBarButtonItem alloc] initWithImage:IMAGE style:UIBarButtonItemStyleBordered target:self action:nil] and not [[UIBarButtonItem alloc] initWithCustomView:]. With the former method the button will animate correctly. Dunno why. Anyway thank you. :-)Utopianism
Localization will be difficult with that approach. I'm not sure why setTitleColor:forState: isn't working for you.Bloodstain
@Bloodstain Hello Greg it appears that in interface builder it only lets you drag a bar button item instead of a UIButton on to the toolbar.Friedland
I think call sizeToFit is very important for thisForeground
Using this approach with IB/Storyboards also does not work as expected. For some reason, when I update the text of the UIButton programmatically (via an IBOutlet), the system libs always manage to reload its contents from the xib shortly after. Anyone figured out how to solve that issue?Extensile
M
4

I was not satisfied with all solutions found on stack overflow becauseI like how UIBarButtonItenm convert images so they are displayed correctly and they can be changed with tint colour. So i discovered this solution that I can use nicely with not much code... End effect is similar to toolbar in facebook and other current apps...

enter image description here

When you change tint colour of view contained in UIBArButtonItem colours of image and title change accordingly, really cool , I do not have to create special images at all.

This code is called from each button like that Competition Button, and also Button is set as referencing outlet...

- (void)selectButton:(UIButton *)sender { 
    _competitionButton.superview.tintColor = [UIColor lightGrayColor];
    _usersButton.superview.tintColor = [UIColor lightGrayColor]; 
    _managementButton.superview.tintColor = [UIColor lightGrayColor];    
    sender.superview.tintColor = [UIColor whiteColor]; 
}

- (IBAction)onCompetitionButtonClick:(UIButton *)sender {
    [self selectButton:sender];
    [_scrollView scrollToPage:0 of:3];
}

In Button like that titled Competition there is only title and in bar button item there is image... This is how I have setup it and it works , maybe there are also other possibilities..

Mulder answered 5/2, 2015 at 15:58 Comment(4)
Well people are blind maybe... for me still very useful solution, I just consider to do it programmatically...Mulder
I have to admit that I have a bit of a hard time figuring out how to translate this storyboard solution in straight code. I need it in code only... (For the record, I didn't down vote your answer.) So far the other solutions I have found have not been satisfactory for me either. Pretty crazy how hard it is to create a UIBarButtonItem that has both an icon and a label... :-(Wetnurse
Mimicked this structure in code, but the tint color is still only applied to the image (which is in the sub-bar button item inside the sub-toolbar) and not on the text label (which is the label of the button next to the sub-toolbar inside the bar button item I'm trying to create... So confusing....Wetnurse
Button Competition has touch up inside selector and referencing outlet assigned , so are all other Button Users and management. Then there is just this one same method called from each selectButton I edited answer with code and also there is paging logic... but that is another story... This works perfekt no issues in apps...Mulder
M
1

So I managed to do my solution programatically... Some users where complaining it does not work ... So how to create UTToolbar with image and item so that you can change color of button by tint and it magically alters image as well as title label ? My UI editor solution works for sure... In this code can clarify things more and you can do it programatically either...

- (void)loadToolbar {
    NSMutableArray *items = NSMutableArray.new;
    [items add:[UIBarButtonItem createWithItem:UIBarButtonSystemItemFlexibleSpace :nil :nil]];
    for (uint pageIndex = 0; pageIndex < _controllers.count; ++pageIndex) {
        UIView *itemView = [UIView.alloc initWithFrame:CGRectMake(0, 0, 100, 44)];
        itemView.backgroundColor = [UIColor clearColor];
        itemView.tintColor = [UIColor orangeColor];
        [itemView addSubview:[self createToolbarForItemView:pageIndex]];
        [itemView addSubview:[self createButtonForItemView:pageIndex]];
        UIBarButtonItem *item = [UIBarButtonItem.alloc initWithCustomView:itemView];
        item.style = UIBarButtonItemStylePlain;
        [items add:item];
        [items add:[UIBarButtonItem createWithItem:UIBarButtonSystemItemFlexibleSpace :nil :nil]];
    }
    [_toolbar setItems:items];
}

- (UIButton *)createButtonForItemView:(uint)pageIndex {
    UIButton *itemButton = [UIButton buttonWithType:UIButtonTypeSystem];
    itemButton.frame = CGRectMake(0, 0, 100, 44);
    itemButton.titleLabel.font = [UIFont systemFontOfSize:11];
    itemButton.contentEdgeInsets = UIEdgeInsetsMake(30, 0, 0, 0);
    itemButton.text = [_controllers[pageIndex] tabTitle];
    itemButton.touchUp = ^(UIButton *sender) {
        for (UIButton *button in _buttons) button.superview.tintColor = UI.toolBarInactiveButtonTextColor;
        sender.superview.tintColor = UI.toolBarActiveButtonTextColor;
        [self showPage:pageIndex];
    };
    [_buttons add:itemButton];
    return itemButton;
}

- (UIToolbar *)createToolbarForItemView:(uint)pageIndex {
    UIToolbar *itemToolbar = [UIToolbar.alloc initWithFrame:CGRectMake(0, 0, 100, 44)];
    itemToolbar.tintColor = nil;
    itemToolbar.barStyle = _toolbar.barStyle;
    itemToolbar.translucent = _toolbar.translucent;
    UIBarButtonItem *imageItem = [_controllers[pageIndex] tabImageItem];
    imageItem.style = UIBarButtonItemStylePlain;
    imageItem.tintColor = nil;
    imageItem.imageInsets = UIEdgeInsetsMake(-10, 0, 0, 0);
    itemToolbar.items = @[
            [UIBarButtonItem createWithItem:UIBarButtonSystemItemFlexibleSpace :nil :nil],
            imageItem,
            [UIBarButtonItem createWithItem:UIBarButtonSystemItemFlexibleSpace :nil :nil]
    ];
    return itemToolbar;
}
Mulder answered 15/5, 2016 at 18:41 Comment(2)
Does that position the label beneath the button?Gaggle
Yes ? Like in my first answer you see on picture... You can control position by tuning itemButton.contentEdgeInsets = UIEdgeInsetsMake(30, 0, 0, 0);Mulder
S
0

I solved this problem as follows:

[Button **setTitleColor**:[UIColor colorWithRed:129/255.0f green:124/255.0f blue:110/255.0f alpha:1.0f] forState:**UIControlStateHighlighted**];
Shortly answered 20/4, 2015 at 6:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.