When I try to use an image for a UIBarButtonItem, the text isn't shown. Is there a way to show both the text and the image?
6 Answers
You can init the UIBarButtonItem with a custom view that has both image and text. Here's a sample that uses a UIButton.
UIImage *chatImage = [UIImage imageNamed:@"08-chat.png"];
UIButton *chatButton = [UIButton buttonWithType:UIButtonTypeCustom];
[chatButton setBackgroundImage:chatImage forState:UIControlStateNormal];
[chatButton setTitle:@"Chat" forState:UIControlStateNormal];
chatButton.frame = (CGRect) {
.size.width = 100,
.size.height = 30,
};
UIBarButtonItem *barButton= [[[UIBarButtonItem alloc] initWithCustomView:chatButton] autorelease];
self.toolbar.items = [NSArray arrayWithObject:barButton];

- 12,142
- 3
- 43
- 40
-
For the last line I get an error message saying "Request for member 'toolbar' is something not a structure or a union. How do I do it using self.navigationItem.rightBarButtonItem? – node ninja Oct 11 '10 at 03:30
-
1In that case, replace the last line with `self.navigationItem.rightBarButtonItem = barButton;`. Or you can use this method: http://developer.apple.com/library/ios/documentation/uikit/reference/UINavigationItem_Class/Reference/UINavigationItem.html#//apple_ref/doc/uid/TP40006933-CH3-SW17. – Kris Markel Oct 11 '10 at 03:39
-
What happens if you use the setRightBarButtonItem:animated: method? – Kris Markel Oct 11 '10 at 03:44
-
2`[self.navigationItem setRightBarButtonItem:barButton animated:YES];` – Kris Markel Oct 11 '10 at 06:04
-
Yes, that worked! Not what I expected, but it shows both text and graphics. – node ninja Oct 11 '10 at 10:04
-
6It's not necessary to use a background image - you can just set the title and image of the UIButton and the image will automatically appear to the left of the text. – Bill Nov 25 '11 at 01:51
-
1Bill:How to just set title and image?```UIImage *image = [[UIImage imageNamed:@"Game.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithImage:image style:UIBarButtonItemStylePlain target:self action:@selector(refreshPropertyList:)]; button.title=@"3333";``` It doesn't work. – Gank Jun 10 '14 at 16:49
I suggest a way how to do this using Storyboard:
- Drag and drop to ToolBar usual UIView. It automatically will be wrapped to Bar Button Item. Adjust View width in "Size inspector". Change background color of View to clear color.
Put UIButton and UILabel inside a View. You can use constraints to adjust their positions. Also you can put thier outside of a View, for example, little higher or less (like on my picture). Put Default and Highlighted images for UIButton.
Copy Bar Button Item and adjust another buttons. Add Flexible spaces.
Create outlets.
Done :). When you run app, you get Tool Bar like this:
P.S. Here you can read how to create UIToolbar subclass using .xib
-
Nice solution. I made both the items UIButtons and put them in a vertical stack view. – user3717478 May 15 '20 at 09:48
-
Note to future self and other people struggling with this: if you are using a Navigation Controller Toolbar and are trying to do this in the "Toolbar Items" dropdown, make a dummy Toolbar and then copy the Bar Button Item over to Toolbar Items. – Michael Plischke Nov 09 '22 at 22:45
Swift 4.2 with target
extension UIBarButtonItem {
convenience init(image :UIImage, title :String, target: Any?, action: Selector?) {
let button = UIButton(type: .custom)
button.setImage(image, for: .normal)
button.setTitle(title, for: .normal)
button.frame = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)
if let target = target, let action = action {
button.addTarget(target, action: action, for: .touchUpInside)
}
self.init(customView: button)
}
}

- 23,101
- 16
- 132
- 246
-
it works. Any idea where the pregnant pauses come from between button press and arrival into the action specified? – Anton Tropashko Jul 30 '19 at 14:17
-
@AntonTropashko The problem is (1) the custom view makes it slower and (2) this is not the correct way to customize the Back button. – matt Jul 30 '19 at 14:29
-
3Add this line to get rid of the left space: button.imageEdgeInsets = UIEdgeInsets(top: 0, left: -13.0, bottom: 0, right: 0) – Aydinozkan Nov 25 '19 at 08:10
-
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;

- 9,217
- 3
- 42
- 59

- 768
- 7
- 19
Kris Markel's answer is a good start (only < iOS7), but if you use tint color, it wount work for the image and the highlighted state of the button.
I've created a category that will create a UIBarButtonItem (leftBarButtonItem) that looks and behaves like a normal iOS7 back button. Have a look at: https://github.com/Zero3nna/UIBarButtonItem-DefaultBackButton

- 2,770
- 30
- 28
Swift Update for UIBarButtonItem with a custom view that has both image and text.
var chatImage: UIImage = UIImage(named: "YourImageName")
var rightButton : UIButton = UIButton(type: UIButtonType.custom)
rightButton.setBackgroundImage(rightImage, for: .normal)
rightButton.setTitle(title, for: .normal)
rightButton.frame.size = CGSize(width: 100, height: 30)
let menuUIBarButtonItem = UIBarButtonItem(customView: rightButton)