How to make custom UIBarButtonItem with image and label?

IosObjective CIos7

Ios Problem Overview


I would like to make a custom UIBarButtonItem that contains both image and text, something like this:

enter image description here

I tried subclassing UIBarButtonItem and overriding this method:

- (UIView *)customView
{
    if (!self.storedView) {
    
        UIView *temp = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 120, 44)];
        UIImageView *tempImageView = [[UIImageView alloc] initWithImage:self.image];
        tempImageView.frame = CGRectMake(0, 0, self.image.size.width, self.image.size.height);
        UILabel *tempLabel = [[UILabel alloc] initWithFrame:CGRectMake(44, 0, 100, 44)];
        tempLabel.text = @"text";
        [temp addSubview:tempImageView];
        [temp addSubview:tempLabel];
        self.storedView = temp;
    }
    return self.storedView;
}

And I use it like this:

UIBarButtonItem *left = [[LeftItem alloc] initWithTitle:@"Settings" style:UIBarButtonItemStylePlain target:self action:@selector(settingsPressed)];
left.title = @"Settings";
left.image = [UIImage imageNamed:@"settings.png"];
self.navigationItem.leftBarButtonItem = left;

But using this I only get the image, but not label. What am I doing wrong?

Ios Solutions


Solution 1 - Ios

UIButton *button =  [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:[UIImage imageNamed:@"image.png"] forState:UIControlStateNormal];
[button addTarget:target action:@selector(buttonAction:)forControlEvents:UIControlEventTouchUpInside];
[button setFrame:CGRectMake(0, 0, 53, 31)];
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(3, 5, 50, 20)];
[label setFont:[UIFont fontWithName:@"Arial-BoldMT" size:13]];
[label setText:title];
label.textAlignment = UITextAlignmentCenter;
[label setTextColor:[UIColor whiteColor]];
[label setBackgroundColor:[UIColor clearColor]];
[button addSubview:label];
UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithCustomView:button];
self.navigationItem.leftBarButtonItem = barButton;

Solution 2 - Ios

You can add a custom view to the UIBarButtonItem.

In iOS 7, there is a new buttonType called UIButtonTypeSystem for UIButton which serve your purpose. Try this,

UIView* leftButtonView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 110, 50)];

UIButton* leftButton = [UIButton buttonWithType:UIButtonTypeSystem];
leftButton.backgroundColor = [UIColor clearColor];
leftButton.frame = leftButtonView.frame;
[leftButton setImage:[UIImage imageNamed:<YourImageName>] forState:UIControlStateNormal];
[leftButton setTitle:@"YourTitle" forState:UIControlStateNormal];
leftButton.tintColor = [UIColor redColor]; //Your desired color.
leftButton.autoresizesSubviews = YES;
leftButton.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin;
[leftButton addTarget:self action:@selector(<YourTargetMethod>) forControlEvents:UIControlEventTouchUpInside];
[leftButtonView addSubview:leftButton];

UIBarButtonItem* leftBarButton = [[UIBarButtonItem alloc]initWithCustomView:leftButtonView];
self.navigationItem.leftBarButtonItem = leftBarButton;

Updated Swift code,

let leftButtonView = UIView.init(frame: CGRect(x: 0, y: 0, width: 110, height: 50))

let leftButton = UIButton.init(type: .system)
leftButton.backgroundColor = .clear
leftButton.frame = leftButtonView.frame
leftButton.setImage(UIImage.init(imageLiteralResourceName: <YourImageName>), for: .normal)
leftButton.setTitle("YourTitle", for: .normal)
leftButton.tintColor = .red //Your desired color.
leftButton.autoresizesSubviews = true
leftButton.autoresizingMask = [.flexibleWidth , .flexibleHeight]
leftButton.addTarget(self, action: #selector(<YourTargetMethod>), for: .touchUpInside)
leftButtonView.addSubview(leftButton)
        
let leftBarButton = UIBarButtonItem.init(customView: leftButtonView)
navigationItem.leftBarButtonItem = leftBarButton
    

Solution 3 - Ios

If your BarButtonItem is in Storyboard, you can drag another Button into BarButtonItem, so there will be a Button inside the BarButtonItem, you can add both image and label to the button.

Solution 4 - Ios

a SWIFT version

    let button =  UIButton(type: .Custom)
    button.setImage(UIImage(named: "icon_right"), forState: .Normal)
        button.addTarget(self, action: "buttonAction", forControlEvents: .TouchUpInside)
    button.frame = CGRectMake(0, 0, 53, 31)
    button.imageEdgeInsets = UIEdgeInsetsMake(-1, 32, 1, -32)//move image to the right
    let label = UILabel(frame: CGRectMake(3, 5, 50, 20))
    label.font = UIFont(name: "Arial-BoldMT", size: 16)
    label.text = "title"
    label.textAlignment = .Center
    label.textColor = UIColor.whiteColor()
    label.backgroundColor =   UIColor.clearColor()
    button.addSubview(label)
    let barButton = UIBarButtonItem(customView: button)
    self.navigationItem.rightBarButtonItem = barButton

Solution 5 - Ios

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

UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:[UIImage imageNamed:@"settings.png"] forState:UIControlStateNormal];
[button setTitle:@"Settings" forState:UIControlStateNormal];
[button addTarget:self action:@selector(buttonAction:)forControlEvents:UIControlEventTouchUpInside];
[button sizeToFit];
UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
self.navigationItem.leftBarButtonItem = barButtonItem;

this can be done using interface builder just by dragging a UIButton to the left bar button slot on a navigation bar.

Solution 6 - Ios

The problem with the accepted answer is that the UIBarButtonItem text does not change when highlighted. The code below will display text plus an image. The UIEdgeInsetsMake moves the text to the left and the image to the right.

UIButton *button =  [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self action:@selector(myButtonEvent:) 
             forControlEvents:UIControlEventTouchUpInside];
[button setFrame:CGRectMake(0, 0, 53, 32)];

[button setTitle:title forState:UIControlStateNormal];
[button setTitleColor:[UIColor whiteColor] 
                 forState:UIControlStateNormal];
[button setTitleColor:[UIColor lightGrayColor] 
                 forState:UIControlStateHighlighted];
button.titleEdgeInsets = UIEdgeInsetsMake(-2, -20, 2, 20);
button.titleLabel.font = font;
button.titleLabel.textAlignment = NSTextAlignmentLeft;

UIImage *image = [UIImage imageNamed:@"imageName"];
[button setImage:image 
        forState:UIControlStateNormal];
button.imageEdgeInsets = UIEdgeInsetsMake(-1, 32, 1, -32);
UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithCustomView:button];

Solution 7 - Ios

I posted answer that handles tint colour and image simmilar to normal uibarbuttonitem here... https://stackoverflow.com/a/28348461/925135

Solution 8 - Ios

Another approach with NSAttributedString:

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:@"Button Text"];
NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init];
textAttachment.image = [UIImage imageNamed:@"buttonImage"];
textAttachment.bounds = CGRectMake(0, -3, textAttachment.image.size.width, textAttachment.image.size.height); //the origin y value depends on the size of the image to get a perfect fit
NSAttributedString *attrStringWithImage = [NSAttributedString attributedStringWithAttachment:textAttachment];
[attributedString replaceCharactersInRange:NSMakeRange(0, 0) withAttributedString:attrStringWithImage]; // Adding the image at the beginning
[customButton setAttributedTitle:attributedString forState:UIControlStateNormal];
[customButton sizeToFit];
[customButton addTarget:self action:@selector(back:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *back = [[UIBarButtonItem alloc] initWithCustomView:customButton];

Solution 9 - Ios

Here's my solution based on previous answers. May be will be helpful.

extension UIBarButtonItem {
    static func button(image: UIImage, title: String, target: Any, action: Selector) -> UIBarButtonItem {
        let button = UIButton()
        button.setImage(image, for: .normal)
        button.addTarget(target, action: action, for: .touchUpInside)
        button.setTitle(title, for: .normal)
        button.sizeToFit()
        return UIBarButtonItem(customView: button)
    }
}

Solution 10 - Ios

UIImage *image = [UIImage imageNamed:@"icon.png"];
UIImage *backgroundSelected = [UIImage imageNamed:@"icon_selected.png"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self action:@selector(ButtonTapped:event:)forControlEvents:UIControlEventTouchUpInside]; //adding action
[button setBackgroundImage:image forState:UIControlStateNormal];
[button setBackgroundImage:backgroundSelected forState:UIControlStateSelected];
button.frame = CGRectMake(0 ,0,35,35);

then make that button as your custom barbutton

UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithCustomView:button];
self.navigationItem.leftBarButtonItem = barButton;

Solution 11 - Ios

This is the updated version of ripegooseberry's answer for Swift 3

    let button =  UIButton(type: .custom)
    button.setImage(UIImage(named: "icon_right"), for: .normal)
    button.addTarget(self, action: Selector(("buttonAction")), for: .touchUpInside)
    button.frame = CGRect(x: 0, y: 0, width: 53, height: 31)
    button.imageEdgeInsets = UIEdgeInsetsMake(-1, 32, 1, -32)//move image to the right
    let label = UILabel(frame: CGRect(x: 3, y: 5, width: 50, height: 20))
    label.font = UIFont(name: "Arial-BoldMT", size: 16)
    label.text = "title"
    label.textAlignment = .center
    label.textColor = UIColor.white
    label.backgroundColor =   UIColor.clear
    button.addSubview(label)
    let barButton = UIBarButtonItem(customView: button)
    self.navigationItem.rightBarButtonItem = barButton

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDvoleView Question on Stackoverflow
Solution 1 - IoskarthikaView Answer on Stackoverflow
Solution 2 - IosramgandhiView Answer on Stackoverflow
Solution 3 - Ios水清木华View Answer on Stackoverflow
Solution 4 - IosdrpaweloView Answer on Stackoverflow
Solution 5 - IossKhanView Answer on Stackoverflow
Solution 6 - IosbbarnhartView Answer on Stackoverflow
Solution 7 - IosRenetikView Answer on Stackoverflow
Solution 8 - IosGabriel CandiaView Answer on Stackoverflow
Solution 9 - Iosanatoliy_vView Answer on Stackoverflow
Solution 10 - IosmrunmayaView Answer on Stackoverflow
Solution 11 - IosJipZipJibView Answer on Stackoverflow