I followed the tutorial below to customize the UINavigationBar.
http://foobarpig.com/iphone/uinavigationbar-with-solid-color-or-image-background.html
I applied a background image in the UINavigationBar, however, I do not know how to customize the back button. At the moment, the default back button does not suits the look & feel of the customized UINavigationBar.
Please teach me how to change the background color or image of the default back button. Thank you.
I've written the following categories to customize the back button:
UIBarButtonItem+StyledButton.h
#interface UIBarButtonItem (StyledButton)
+ (UIBarButtonItem *)styledBackBarButtonItemWithTarget:(id)target selector:(SEL)selector;
+ (UIBarButtonItem *)styledCancelBarButtonItemWithTarget:(id)target selector:(SEL)selector;
+ (UIBarButtonItem *)styledSubmitBarButtonItemWithTitle:(NSString *)title target:(id)target selector:(SEL)selector;
#end
UIBarButtonItem+StyledButton.m
#implementation UIBarButtonItem (StyledButton)
+ (UIBarButtonItem *)styledBackBarButtonItemWithTarget:(id)target selector:(SEL)selector;
{
UIImage *image = [UIImage imageNamed:#"button_back"];
image = [image stretchableImageWithLeftCapWidth:20.0f topCapHeight:20.0f];
NSString *title = NSLocalizedString(#"Back", nil);
UIFont *font = [UIFont boldSystemFontOfSize:12.0f];
UIButton *button = [UIButton styledButtonWithBackgroundImage:image font:font title:title target:target selector:selector];
button.titleLabel.textColor = [UIColor blackColor];
CGSize textSize = [title sizeWithFont:font];
CGFloat margin = (button.frame.size.height - textSize.height) / 2;
CGFloat marginRight = 7.0f;
CGFloat marginLeft = button.frame.size.width - textSize.width - marginRight;
[button setTitleEdgeInsets:UIEdgeInsetsMake(margin, marginLeft, margin, marginRight)];
[button setTitleColor:[UIColor colorWithRed:53.0f/255.0f green:77.0f/255.0f blue:99.0f/255.0f alpha:1.0f] forState:UIControlStateNormal];
return [[[UIBarButtonItem alloc] initWithCustomView:button] autorelease];
}
+ (UIBarButtonItem *)styledCancelBarButtonItemWithTarget:(id)target selector:(SEL)selector;
{
UIImage *image = [UIImage imageNamed:#"button_square"];
image = [image stretchableImageWithLeftCapWidth:20.0f topCapHeight:20.0f];
NSString *title = NSLocalizedString(#"Cancel", nil);
UIFont *font = [UIFont boldSystemFontOfSize:12.0f];
UIButton *button = [UIButton styledButtonWithBackgroundImage:image font:font title:title target:target selector:selector];
button.titleLabel.textColor = [UIColor blackColor];
[button setTitleColor:[UIColor colorWithRed:53.0f/255.0f green:77.0f/255.0f blue:99.0f/255.0f alpha:1.0f] forState:UIControlStateNormal];
return [[[UIBarButtonItem alloc] initWithCustomView:button] autorelease];
}
+ (UIBarButtonItem *)styledSubmitBarButtonItemWithTitle:(NSString *)title target:(id)target selector:(SEL)selector;
{
UIImage *image = [UIImage imageNamed:#"button_submit"];
image = [image stretchableImageWithLeftCapWidth:20.0f topCapHeight:20.0f];
UIFont *font = [UIFont boldSystemFontOfSize:12.0f];
UIButton *button = [UIButton styledButtonWithBackgroundImage:image font:font title:title target:target selector:selector];
button.titleLabel.textColor = [UIColor whiteColor];
[button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
return [[[UIBarButtonItem alloc] initWithCustomView:button] autorelease];
}
UIButton+StyledButton.h
#interface UIButton (UIButton_StyledButton)
+ (UIButton *)styledButtonWithBackgroundImage:(UIImage *)image font:(UIFont *)font title:(NSString *)title target:(id)target selector:(SEL)selector;
#end
UIButton+StyledButton.m
#implementation UIButton (UIButton_StyledButton)
+ (UIButton *)styledButtonWithBackgroundImage:(UIImage *)image font:(UIFont *)font title:(NSString *)title target:(id)target selector:(SEL)selector
{
CGSize textSize = [title sizeWithFont:font];
CGSize buttonSize = CGSizeMake(textSize.width + 20.0f, image.size.width);
UIButton *button = [[[UIButton alloc] initWithFrame:CGRectMake(0.0f, 0.0f, buttonSize.width, buttonSize.height)] autorelease];
[button addTarget:target action:selector forControlEvents:UIControlEventTouchUpInside];
[button setBackgroundImage:image forState:UIControlStateNormal];
[button setTitle:title forState:UIControlStateNormal];
[button.titleLabel setFont:font];
return button;
}
#end
It's easy to use, e.g.:
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.leftBarButtonItem = [UIBarButtonItem styledBackBarButtonItemWithTarget:self selector:#selector(dismissModalViewController)];
self.navigationItem.rightBarButtonItem = [UIBarButtonItem styledSubmitBarButtonItemWithTitle:NSLocalizedString(#"Done", nil) target:self selector:#selector(doneButtonTouched:)];
}
The above code is from a project that's still work-in-progress, so it could be cleaned up a bit, but it works as supposed to. Use images without text as buttons and make sure they're stretchable (i.e. don't make the images too small and be careful with gradients). The image of the back button in the following example is only 31 x 30 pixels, but it's stretched to make the text fit.
Some examples of the results:
Back button
Cancel / Done buttons
I have used this code a few times:
- (void)viewDidLoad {
[super viewDidLoad];
// Set the custom back button
UIImage *buttonImage = [UIImage imageNamed:#"back_button.png"];
//create the button and assign the image
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:buttonImage forState:UIControlStateNormal];
//set the frame of the button to the size of the image (see note below)
button.frame = CGRectMake(0, 0, buttonImage.size.width, buttonImage.size.height);
[button addTarget:self action:#selector(back) forControlEvents:UIControlEventTouchUpInside];
//create a UIBarButtonItem with the button as a custom view
UIBarButtonItem *customBarItem = [[UIBarButtonItem alloc] initWithCustomView:button];
self.navigationItem.leftBarButtonItem = customBarItem;
// Cleanup
[customBarItem release];
}
-(void)back {
// Tell the controller to go back
[self.navigationController popViewControllerAnimated:YES];
}
From this website.
Hope it helps!
You have to build a custom UIButton and pass it to UIBarButton initWithCustomView.
Here is what you do.
1) Add custom buttons to your navigation item in the Interface Builder:
2) In the code do the following:
#define IS_IOS7 ([[[UIDevice currentDevice] systemVersion] compare:#"7.0" options:NSNumericSearch] != NSOrderedAscending)
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
if (IS_IOS7) {
[self shiftView:self.navigationItem.leftBarButtonItem.customView horizontallyBy:-11];
[self shiftView:self.navigationItem.rightBarButtonItem.customView horizontallyBy:11];
}
}
- (void)shiftView:(UIView*)view horizontallyBy:(int)offset {
CGRect frame = view.frame;
frame.origin.y += offset;
view.frame = frame;
}
Related
I am newbie trying to make an app similar to Notes app of iPhone using UITextView.
I am getting the textView and lines and it is working fine.
My problem is that I want to add a UINavigationBar and back button on it.
And I want to add a UIToolBar at the bottom and 2 toolBarItems on it how to do this programmetically. Any help will be a great push up for me..
below is the code snippet.
NoteView.h
#interface NoteView : UITextView <UITextViewDelegate,UITabBarControllerDelegate>
{
}
NoteView.m
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor colorWithRed:0.6f green:0.6f blue:1.0f alpha:1.0f];
self.font = [UIFont fontWithName:#"MarkerFelt-Thin" size:20];
self.contentMode = UIViewContentModeRedraw;
}
return self;
}
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.2f].CGColor);
CGContextSetLineWidth(context, 1.0f);
CGContextBeginPath(context);
NSUInteger numberOfLines = (self.contentSize.height + self.bounds.size.height) / self.font.leading;
CGFloat baselineOffset = 6.0f;
for (int x = 0; x < numberOfLines; x++) {
CGContextMoveToPoint(context, self.bounds.origin.x, self.font.leading*x + 0.5f + baselineOffset);
CGContextAddLineToPoint(context, self.bounds.size.width, self.font.leading*x + 0.5f + baselineOffset);
}
CGContextClosePath(context);
CGContextStrokePath(context);
}
AddNotesViewController.h
#interface AddNotesViewController : UIViewController <UITextViewDelegate,UITabBarDelegate>
{
NoteView *note;
}
#property (nonatomic, retain) NoteView *note;
#end
AddNotesViewController.m
- (void)loadView
{
[super loadView];
self.note = [[[NoteView alloc] initWithFrame:self.view.bounds] autorelease];
[self.view addSubview:note];
note.delegate = self;
note.text=#"";
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
[note setNeedsDisplay];
}
- (void)textViewDidBeginEditing:(UITextView *)textView
{
CGRect frame = self.view.bounds;
frame.size.height -= KEYBOARD_HEIGHT;
note.frame = frame;
}
- (void)textViewDidEndEditing:(UITextView *)textView
{
note.frame = self.view.bounds;
}
- (BOOL)textView:(UITextView *)textView
shouldChangeTextInRange:(NSRange)range
replacementText:(NSString *)text
{
if ([text isEqualToString:#"\n"]) {
[textView resignFirstResponder];
return NO;
}
return YES;
}
Please tell me how and where to add navigation bar , back button and tool bar ,2 toolBarItems on it.Thanks in advance...
Navigation Bar Image
UINavigationBar *navBar = [[self navigationController] navigationBar];
UIImage *image = [UIImage imageNamed:#"TopBar.png"];
[navBar setBackgroundImage:image forBarMetrics:UIBarMetricsDefault];
Back Button
-(void)getBackBtn
{
UIButton *Btn =[UIButton buttonWithType:UIButtonTypeCustom];
[Btn setFrame:CGRectMake(0.0f,0.0f,50.0f,30.0f)];
[Btn setBackgroundImage:[UIImage imageNamed:[NSString stringWithFormat:#"back.png"]] forState:UIControlStateNormal];
//[Btn setTitle:#"OK" forState:UIControlStateNormal];
//Btn.titleLabel.font = [UIFont fontWithName:#"Georgia" size:14];
[Btn addTarget:self action:#selector(backBtnPress:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithCustomView:Btn];
[self.navigationItem setLeftBarButtonItem:addButton];
}
BackButtonAction
-(IBAction)backBtnPress:(id)sender
{
}
View on NavigationBar
For View on navigationBar you can follow my answer Link
use this code....
UIBarButtonItem *addButton = [[UIBarButtonItem alloc]
initWithTitle:NSLocalizedString(#"Back", #"")
style:UIBarButtonItemStyleDone
target:self
action:#selector(YourActionMethod:)];
self.navigationItem.leftBarButtonItem = addButton;
How can I remove the gloss/shine effect from the buttons on navigation bars?
If I customize the navigation bar by using a custom image the buttons are not affected, can I remove the effect from them (the line and glossing), or define a hex color code for the whole button, or even a custom image for them too?
I just went through the process of figuring this out. Basically, you need to create custom stretchable images and use them as the button's background to get rid of the shine. Replacing the back buttons in a UINavigationController is a bit tougher. For that I used a UINavigationControllerDelegate to replace the default back button with my custom button.
Here's some code:
Create a category on UIBarButtonItem that creates your custom button. Here's mine. I use this category to customize both regular bar buttons and back buttons:
#interface UIBarButtonItem (UIBarButtonItem_customBackground)
+ (id) customBarButtonWithTitle:(NSString *)title target:(id)target selector:(SEL)selector;
+ (id) customBackButtonWithTitle:(NSString *)title target:(id)target selector:(SEL)selector;
#end
#implementation UIBarButtonItem (UIBarButtonItem_customBackground)
+ (id) customButtonWithImageNamed:(NSString *)imageName selectedImageNamed:(NSString *)selectedImageName leftCapWidth:(CGFloat)leftCapWidth edgeInsets:(UIEdgeInsets)edgeInsets title:(NSString *)title target:(id)target selector:(SEL)selector {
UIButton* customButton = [UIButton buttonWithType:UIButtonTypeCustom];
[customButton addTarget:target action:selector forControlEvents:UIControlEventTouchUpInside];
customButton.titleLabel.font = [UIFont boldSystemFontOfSize:12.0f];
customButton.titleLabel.shadowColor = [UIColor colorWithRed:0.0f/255.0f green:0.0f/255.0f blue:0.0f/255.0f alpha:0.25f];
customButton.titleLabel.shadowOffset = CGSizeMake(0.0f, -1.0f);
customButton.titleLabel.lineBreakMode = UILineBreakModeTailTruncation;
customButton.titleEdgeInsets = edgeInsets;
UIImage* navButtonBackgroundImage = [[UIImage imageNamed:imageName] stretchableImageWithLeftCapWidth:leftCapWidth topCapHeight:0.0f];
UIImage* navButtonPressedBackgroundImage = [[UIImage imageNamed:selectedImageName] stretchableImageWithLeftCapWidth:leftCapWidth topCapHeight:0.0f];
[customButton setBackgroundImage:navButtonBackgroundImage forState:UIControlStateNormal];
[customButton setTitle:title forState:UIControlStateNormal];
[customButton setBackgroundImage:navButtonPressedBackgroundImage forState:UIControlStateHighlighted];
[customButton setBackgroundImage:navButtonPressedBackgroundImage forState:UIControlStateSelected];
CGSize size = CGSizeMake(30.0f, 30.0f);
if (title != nil) {
size = [[NSString stringWithString:title] sizeWithFont:customButton.titleLabel.font];
}
customButton.frame = CGRectMake(0.0f, 0.0f, size.width + 20.0f, 30.0f);
customButton.layer.shouldRasterize = YES;
customButton.layer.rasterizationScale = [[UIScreen mainScreen] scale];
return [[[UIBarButtonItem alloc] initWithCustomView:customButton] autorelease];
}
+ (id) customBarButtonWithTitle:(NSString *)title target:(id)target selector:(SEL)selector {
return [self customButtonWithImageNamed:#"navButtonBG.png"
selectedImageNamed:#"navButtonPressedBG.png"
leftCapWidth:6.0f
edgeInsets:UIEdgeInsetsMake(0.0f, 5.0f, 0.0f, 5.0f)
title:title
target:target
selector:selector];
}
+ (id) customBackButtonWithTitle:(NSString *)title target:(id)target selector:(SEL)selector {
return [self customButtonWithImageNamed:#"backButtonBG.png"
selectedImageNamed:#"backButtonPressedBG.png"
leftCapWidth:12.0f
edgeInsets:UIEdgeInsetsMake(0.0f, 11.0f, 0.0f, 5.0f)
title:title
target:target
selector:selector];
}
#end
Add the button to your UINavigationBar
UIBarButtonItem* logoutButton = [UIBarButtonItem customBarButtonWithTitle:#"Logout" target:self selector:#selector(logout)];
self.navigationItem.rightBarButtonItem = logoutButton;
If you also want to replace the UINavigationController's back buttons, setup a UINavigationControllerDelegate and implement the willShowViewController method like so:
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if([navigationController.viewControllers count ] > 1) {
UIViewController* backViewController = [navigationController.viewControllers objectAtIndex:(navigationController.viewControllers.count - 2)];
NSString* backText = backViewController.title;
UIBarButtonItem* newBackButton = [UIBarButtonItem customBackButtonWithTitle:backText target:navigationController selector:#selector(popViewControllerAnimated:)];
viewController.navigationItem.leftBarButtonItem = newBackButton;
viewController.navigationItem.hidesBackButton = YES;
}
}
Here are the stretchable images I'm using:
Back button: Pressed:
Regular button: Pressed:
For changing the back button it is not necessary to implement the delegate method uinavigationcontroller.
You only need set the hidesBAckButton property to YES after setting the desired backbutton as #Justin Gallacher explained perfectly.
self.navigationItem.leftBarButtonItem = [UIBarButtonItem customBackButtonWithTitle:#"Back" target:self.navigationController selector:#selector(popViewControllerAnimated:)];
self.navigationItem.hidesBackButton = YES;
you have to use the custom button with images without any gloss effect on the images by which you can get rid of the gloos effect of the button from navbar.
I am using the following code to add a custom navbar to my app. But I want to be able to change the navbar depending on the view, is this possible?
#implementation UINavigationBar (UINavigationBarCategory)
- (void)drawRect:(CGRect)rect
{
UIColor *color = [UIColor colorWithRed:82/255.0 green:80/255.0 blue:81/255.0 alpha:1.0];
UIImage *img = [UIImage imageNamed: #"navbar.png"];
[img drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
self.tintColor = color;
}
#end
If not, is it possible to just add an image to the navbar instead of title text?
I would strongly discourage using a category to override -drawRect on a UINavBar as this design will break on a soon to be released iOS version.
It is very easy to create custom images and buttons to the navBar title though. Here's some code snippets I pulled directly out of production code for one of my apps. It creates a custom image button in the navBar's title area, but it's just as easy to create an image instead:
- (void) viewDidLoad {
UIButton *titleButton = [self buttonForTitleView];
[titleButton setTitle:newTitle forState:UIControlStateNormal];
[titleButton sizeToFit];
self.navigationBar.topItem.titleView = titleButton;
}
- (UIButton *) buttonForTitleView {
if (!_buttonForTitleView) {
UIImage *buttonImage = [UIImage imageNamed:#"button_collection_name2"];
UIImage *pressedButtonImage = [UIImage imageNamed:#"button_collection_name2_pressed"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setBackgroundImage: buttonImage forState : UIControlStateNormal];
[button setBackgroundImage: pressedButtonImage forState : UIControlStateHighlighted];
[button setFrame:CGRectMake(0, 0, buttonImage.size.width, buttonImage.size.height)];
[button setTitleColor:[UIColor colorWithRed:38.0/255.0 green:38.0/255.0 blue:38.0/255.0 alpha:1.0] forState:UIControlStateNormal];
[button setTitleShadowColor:[UIColor colorWithRed:230.0/255.0 green:230.0/255.0 blue:230.0/255.0 alpha:1.0] forState:UIControlStateNormal];
button.titleLabel.adjustsFontSizeToFitWidth = YES;
button.titleLabel.minimumFontSize = 10.0;
button.titleEdgeInsets = UIEdgeInsetsMake(0.0, 10.0, 0.0, 10.0);
button.titleLabel.shadowOffset = (CGSize){ 0, 1 };
[button addTarget:self action:#selector(presentWidgetCollectionSwitchingViewController:) forControlEvents:UIControlEventTouchUpInside];
_buttonForTitleView = [button retain];
}
return _buttonForTitleView;
}
And this is what the button looks like in the app VideoBot:
Here's an example of using an image for the navbar title:
UIImage *titleImage = [UIImage imageNamed:#"navbar_title_image"];
UIImageView *titleImageView = [[[UIImageView alloc] initWithImage:titleImage] autorelease];
UIView *container = [[[UIView alloc] initWithFrame:(CGRect){0.0, 0.0, titleImage.size.width, titleImage.size.height}] autorelease];
container.backgroundColor = [UIColor clearColor];
[container addSubview:titleImageView];
// add the view to the title
self.navigationBar.topItem.titleView= container;
I have an view in my App which has a number of buttons based on the number of items returned by the server. So if the server returns say 10 items, there should be 10 buttons and clicking on each button should call a different person.
For the above purpose I created a custom button class deriving from UIButton.
#implementation HopitalButton
#synthesize index;
#synthesize button_type;
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
UIImage* img = [UIImage imageNamed:#"dr_btn.png"];
[img stretchableImageWithLeftCapWidth:10 topCapHeight:10];
[self setBackgroundImage:img forState:UIControlStateNormal];
[self setTitleColor:[UIColor colorWithRed:0.698 green:0.118 blue:0.376 alpha:1] forState:UIControlStateNormal] ;
[self setFont:[UIFont fontWithName:#"Helvetica Bold" size:13]];
self.titleLabel.textColor = [UIColor colorWithRed:178 green:48 blue:95 alpha:1];
self.adjustsImageWhenHighlighted = YES;
}
return self;
}
- (void)dealloc {
[super dealloc];
}
#end
Now the problem with the above code is that it does not create buttons that look similar to the buttons created by default in Interface builder. The borders are missing.
And I create buttons of the above type by the following code:
HopitalButton* hb = [[HopitalButton alloc] init];
hb.button_type = #"call";
hb.frame = CGRectMake(50, 50 + i * 67, 220, 40);
[self.scroll_view addSubview:hb];
[hb setTitle:[[[self.office_full_list objectAtIndex:i] objectForKey:#"Staff" ]objectForKey:#"FullName"] forState:UIControlStateNormal];
hb.index = [NSNumber numberWithInt:[self.button_items count]];
[self.button_items insertObject:hb atIndex:[self.button_items count]];
[hb addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
I am not finding a way to set the button type for this custom button.
Is there a way i can do it ? Or is there a better way to design the code.
You first start with a stretchable image with a border:
alt text http://grab.by/4lP
Then you make a button with the stretched image as the background and apply text.
INDEX_OFFSET = 82753; // random
UIButton *sampleButton = [UIButton buttonWithType:UIButtonTypeCustom];
[sampleButton setFrame:CGRectMake(kLeftMargin, 10, self.view.bounds.size.width - kLeftMargin - kRightMargin, 52)];
[sampleButton setTitle:#"Button Title" forState:UIControlStateNormal];
[sampleButton setFont:[UIFont boldSystemFontOfSize:20]];
[sampleButton setTag:<INDEX>+INDEX_OFFSET];
[sampleButton setBackgroundImage:[[UIImage imageNamed:#"redButton.png"] stretchableImageWithLeftCapWidth:10.0 topCapHeight:0.0] forState:UIControlStateNormal];
[sampleButton addTarget:self action:#selector(buttonPressed) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:sampleButton];
Obviously, you will need to adjust the frame origin and size to match your app, as well as the target, selector, and title. And
[sampleButton setFont:[UIFont boldSystemFontOfSize:20]];
setFont is now deprecated, use titleLabel.font property instead
sampleButton.titleLabel.font = [UIFont boldSystemFontOfSize:20];
you can use individual class for custom Roundrect button which can be useful in whole project with your specific frame style as below
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#interface CustomRoundRectButton : UIButton
#end
#import "CustomRoundRectButton.h"
#implementation CustomRoundRectButton
- (void)drawRect:(CGRect)rect
{
[[self layer] setMasksToBounds:YES];
[self.layer setCornerRadius:10.0f];
[self.layer setBorderColor:[UIColor grayColor].CGColor];
[self.layer setBorderWidth:1.0];
}
#end
In this you have to select button type custom and select its class as CustomRoundRectButton.
For Simple custom button we can use as below
-(UIBarButtonItem*)BackButton
{
UIButton*btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setImage:[UIImage imageNamed:#"back.png"] forState:UIControlStateNormal];
[btn setFrame:CGRectMake(0, 0, 30, 30)];
[btn addTarget:self action:#selector(actionBack) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem*barBtn = [[[UIBarButtonItem alloc] initWithCustomView:btn] autorelease];
return barBtn;
}
Shouldn't you be calling initWithFrame: rect instead of:
HopitalButton* hb = [[HopitalButton alloc] init];
My iPhone view adds some custom buttons to its toolbar. Each button has both an image and textual title, and is created like this:
UIBarButtonItem *fooButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"foo.png"] style:UIBarButtonItemStylePlain target:self action:#selector(fooButtonPressed:)];
fooButton.title=#"Foo";
The title's text displays very dim; it looks like it has an alpha of about 0.5. If I use the default UIToolBar barStyle, I can't read the text at all. When using UIBarStyleBlack I can read the text but it still looks very dim.
I also tried initWithTitle, and then set the image property; the results are identical.
Is there a way to brighten up the text? I am hoping for a look similar to a UITabBar whose items have both an image and title.
Thanks for the help!
I was trying to use the UIBarButtonItem to display both an image and a button, but I'm pretty sure it's locked down to display one or the other. Using the basic idea from this thread I came up with a solution using a UIButton and a background image. The biggest flaw of what I've done is that when the title text varies in size a lot, the background image stretches causing the rounded corners to look a little off.
CustomBarButtonItem.h
#import <UIKit/UIKit.h>
#interface CustomBarButtonItem : UIBarButtonItem {}
- (id) initWithImage:(UIImage *)image title:(NSString *)title target:(id)target action:(SEL)action;
#end
#interface UIBarButtonItem (CustomBarButtonItem)
+ (UIBarButtonItem *) barButtonItemWithImage:(UIImage *)image title:(NSString *)title target:(id)target action:(SEL)action;
#end
CustomBarButtonItem.m
#import "CustomBarButtonItem.h"
#implementation CustomBarButtonItem
- (id) initWithImage:(UIImage *)image title:(NSString *)title target:(id)target action:(SEL)action {
UIButton *barButton = [UIButton buttonWithType:UIButtonTypeCustom];
UIFont *font = [UIFont boldSystemFontOfSize:13];
barButton.titleLabel.font = font;
barButton.titleLabel.shadowOffset = CGSizeMake(0, -1);
barButton.titleEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 5);
[barButton setImage:image forState:UIControlStateNormal];
[barButton setTitle:title forState:UIControlStateNormal];
[barButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[barButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateHighlighted];
[barButton setTitleShadowColor:[[UIColor blackColor] colorWithAlphaComponent:0.5] forState:UIControlStateNormal];
[barButton setBackgroundImage:[UIImage imageNamed:#"bar-button-item-background.png"] forState:UIControlStateNormal];
barButton.frame = CGRectMake(0, 0, image.size.width + 15 + [title sizeWithFont:font].width, 30);
if (self = [super initWithCustomView:barButton]) {
self.target = target;
self.action = action;
}
return self;
}
#end
#implementation UIBarButtonItem (CustomBarButtonItem)
+ (UIBarButtonItem *) barButtonItemWithImage:(UIImage *)image title:(NSString *)title target:(id)target action:(SEL)action {
return [[[CustomBarButtonItem alloc] initWithImage:image title:title target:target action:action] autorelease];
}
#end
Sample usage:
UIBarButtonItem *customButtonItem = [UIBarButtonItem barButtonItemWithImage:[UIImage imageNamed:#"calendar.png"] title:#"Add to calendar" target:self action:#selector(addToCalendar)];
My background image for the button is:
Johnus's solution is pretty useful.
But I've tried it and a little problem occured: the action was not sent to the bar button item, so I've modified the initializer a little :
- (id) initWithImage:(UIImage *)image title:(NSString *)title target:(id)target action:(SEL)action {
UIButton *barButton = [UIButton buttonWithType:UIButtonTypeCustom];
UIFont *font = [UIFont boldSystemFontOfSize:13];
barButton.titleLabel.font = font;
barButton.titleLabel.shadowOffset = CGSizeMake(0, -1);
barButton.titleEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 5);
[barButton setImage:image forState:UIControlStateNormal];
[barButton setTitle:title forState:UIControlStateNormal];
[barButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[barButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateHighlighted];
[barButton setTitleShadowColor:[[UIColor blackColor] colorWithAlphaComponent:0.5] forState:UIControlStateNormal];
[barButton setBackgroundImage:[UIImage imageNamed:#"bar-button-item-background.png"] forState:UIControlStateNormal];
barButton.frame = CGRectMake(0, 0, image.size.width + 15 + [title sizeWithFont:font].width, 30);
if (self = [super initWithCustomView:barButton]) {
self.target = target;
self.action = action;
// I've added just one line of code here
[barButton addTarget:target
action:action
forControlEvents:UIControlEventTouchUpInside];
}
return self;
}
The answers here are nice, however its often a little easier to use composition rather than inheritance with UIKit classes.
Create a bar item like so:
_accountBarItem =
[[UIBarButtonItem alloc] initWithCustomView:[CustomerBarView buttonWithImage:
[UIImage imageNamed:#"Account.png"] text:#"Account"]];
[_accountBarItem setTarget:self];
[_accountBarItem setAction:#selector(accountButtonPressed)];
Implementation of Custom View with Image and Label
#implementation CustomBarView
+ (instancetype)buttonWithImage:(UIImage*)image text:(NSString*)text
{
CustomBarView* button = [[CustomBarView alloc] initWithFrame:CGRectMake(0, 0, 44, 44)];
[button setText:text];
[button setImage:image];
return button;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
_uiButton = [UIButton buttonWithType:UIButtonTypeCustom];
[self addSubview:_uiButton];
_label = [[UILabel alloc] initWithFrame:CGRectZero];
[_label setTextColor:[UIColor whiteColor]];
[_label setFont:[UIFont boldApplicationFontOfSize:9]];
[_label setBackgroundColor:[UIColor clearColor]];
[_label setTextAlignment:NSTextAlignmentCenter];
[self addSubview:_label];
}
return self;
}
- (void)setText:(NSString*)text
{
[_label setText:text];
}
- (void)setImage:(UIImage*)image
{
[_uiButton setImage:image forState:UIControlStateNormal];
}
- (void)layoutSubviews
{
[super layoutSubviews];
[_uiButton setFrame:self.bounds];
[_label setFrame:CGRectMake(2, self.height - 13, self.width - 4, 15)];
}
#end