UIToolbar UIBarButtonItem with both image and title has very dim text - iphone

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

Related

how do i achieve this on navigationBar

i want design my navigationBar like following figure, how can i achieve this.is it possible on navigationBar or i don't need navigationBar.
Topics & settings must be buttons, because i want to navigate to another viewController
I don't know whether it is possible on navigation bar.
I saw a similar one using tabbar: Center Button in Tab Bar for iOS
And you can achieve the same thing using : ALToolbar
Also check KLHorizontalselect
Create custom Navigation Bar with custom Delegate for that.. i used this see example bellow..
create CustomNavBar.h file like bellow...
// Created by Paras on 03/12/11.
// Copyright 2010 __MyCompanyName__. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "CustomNavBarDelegate.h"
#interface CustomNavBar : UIView {
NSObject<CustomNavBarDelegate> *delegate;
NSString *strCatOrLoc;
UIButton *btnBack;
UIButton *btnLeft;
UIImageView *imgRightImage;
UILabel *lbl;
UIImageView *imgTitle;
}
#property (nonatomic, retain) UIButton *btnBack;
#property (nonatomic, assign) NSObject<CustomNavBarDelegate> *delegate;
-(void)onclickBack:(id)sender;
- (id) initWithFrame: (CGRect)rect;
-(void)setImage:(UIImage*)img NavTitle:(NSString *)title;
-(void)setTitleImage:(UIImage*)img rightImage:(UIImage *)imgRight;
-(void)setwithoutlogo:(UIImage*)img NavTitle:(NSString *)title;
#end
now see the code of CustomNavBar.m file bellow...
// Created by Paras on 03/12/11.
// Copyright 2010 __MyCompanyName__. All rights reserved.
//
#import "CustomNavBar.h"
#import <QuartzCore/QuartzCore.h>
#import "AppDelegate.h"
#implementation CustomNavBar
#synthesize delegate;
#synthesize btnBack;
#pragma mark -
#pragma mark init methods
- (id) initWithFrame: (CGRect)rect {
if (self == [super initWithFrame:rect]) {
//[self setBackgroundColor:[UIColor colorWithRed:241.0f/255.0f green:241.0f/255.0f blue:237.0f/255.0f alpha:1.0f]];
// [self setBackgroundColor:[UIColor whiteColor]];
btnBack = [UIButton buttonWithType:UIButtonTypeCustom];
btnBack.frame = CGRectMake(10.0, 8.0, 50.0, 28.0);
[btnBack addTarget:self
action:#selector(onclickBack:)
forControlEvents:UIControlEventTouchDown];
btnBack.layer.masksToBounds = YES;
btnBack.layer.cornerRadius = 8.0;
btnBack.layer.borderWidth = 0.5;
btnBack.layer.borderColor = [[UIColor blackColor] CGColor];
//btnBack.titleLabel.textColor = [UIColor blackColor];
// btnBack.titleLabel.text = #"Back";
[btnBack.titleLabel setFont:Arial13];
[btnBack setTitle:#"" forState:UIControlStateNormal];
[btnBack setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
// [btnBack setBackgroundColor:[UIColor colorWithRed:241.0f/255.0f green:241.0f/255.0f blue:237.0f/255.0f alpha:1.0f]];
[btnBack setBackgroundColor:[UIColor clearColor]];
[self addSubview:btnBack];
btnLeft = [UIButton buttonWithType:UIButtonTypeCustom];
btnLeft.frame = CGRectMake(280.0, 8.0, 310.0, 28.0);
[btnLeft addTarget:self
action:#selector(onclickLeft:)
forControlEvents:UIControlEventTouchDown];
[btnLeft setBackgroundColor:[UIColor clearColor]];
[self addSubview:btnLeft];
}
return self;
}
-(void)setImage:(UIImage*)img NavTitle:(NSString *)title {
imgRightImage = [[UIImageView alloc] initWithFrame:CGRectMake(0.0,0.0,320.0,44.0)];
imgRightImage.contentMode = UIViewContentModeScaleAspectFill;
imgRightImage.clipsToBounds = YES;
imgRightImage.layer.masksToBounds = YES;
// imgRightImage.layer.cornerRadius = 11.0;
// imgRightImage.layer.borderWidth = 0.5;
[imgRightImage setImage:img];
[imgRightImage setBackgroundColor:[UIColor clearColor]];
[self addSubview:imgRightImage];
[imgRightImage release];
}
-(void)setwithoutlogo:(UIImage*)img NavTitle:(NSString *)title {
imgRightImage = [[UIImageView alloc] initWithFrame:CGRectMake(275.0,2.0,40.0,40.0)];
imgRightImage.contentMode = UIViewContentModeScaleAspectFill;
imgRightImage.clipsToBounds = YES;
imgRightImage.layer.masksToBounds = YES;
// imgRightImage.layer.cornerRadius = 11.0;
// imgRightImage.layer.borderWidth = 0.5;
//[imgRightImage setImage:img];
[imgRightImage setBackgroundColor:[UIColor clearColor]];
[self addSubview:imgRightImage];
[imgRightImage release];
lbl = [[UILabel alloc] initWithFrame:CGRectMake(70.0, 7.0, 180, 30.0)];
// lbl.font = [UIFont fontWithName:#"Arial" size:20.0];
lbl.font = Arial16;
lbl.numberOfLines = 1;
lbl.tag = 11;
lbl.backgroundColor = [UIColor clearColor];
lbl.textColor = [UIColor blackColor];
lbl.textAlignment = UITextAlignmentCenter;
lbl.text = title;
[self addSubview:lbl];
}
-(void)setTitleImage:(UIImage*)img rightImage:(UIImage *)imgRight {
imgRightImage = [[UIImageView alloc] initWithFrame:CGRectMake(275.0,2.0,40.0,40.0)];
imgRightImage.contentMode = UIViewContentModeScaleAspectFill;
imgRightImage.clipsToBounds = YES;
imgRightImage.layer.masksToBounds = YES;
[imgRightImage setImage:imgRight];
[imgRightImage setBackgroundColor:[UIColor clearColor]];
[self addSubview:imgRightImage];
[imgRightImage release];
imgTitle = [[UIImageView alloc] initWithFrame:CGRectMake(68.0,3.0,200.0,38.0)];
imgTitle.contentMode = UIViewContentModeScaleToFill;
[imgTitle setBackgroundColor:[UIColor clearColor]];
[imgTitle setImage:img];
[self addSubview:imgTitle];
[imgTitle release];
}
-(void)onclickLeft:(id)sender{
NSLog(#">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Nav LeftClick");
[delegate btnleft_clicked:self];
}
-(void)onclickBack:(id)sender {
NSLog(#">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Nav BackClick");
[delegate popViewController:self];
}
#pragma mark -
#pragma mark
- (void)dealloc {
//[array release];
[super dealloc];
}
#end
and after that create Delegate class file like bellow..
#class CustomNavBar;
#protocol CustomNavBarDelegate
#required
- (void)popViewController:(CustomNavBar *)navBar;
-(void)btnleft_clicked:(CustomNavBar *)navBar1;
#end
after use this code in your classes ..For Example..
in .h file import it and then use like bellow..
#import "CustomNavBarDelegate.h"
#class CustomNavBar;
#interface ViewController : UIViewController<CustomNavBarDelegate>
{
CustomNavBar *navBar;
}
- (void)popViewController:(CustomNavBar *)navBar1;
#end
and in .m file define that delegate method and create and add navigation like bellow...
- (void)viewDidLoad
{
navBar = [[CustomNavBar alloc] initWithFrame:CGRectMake(0, 0, 322, 44)];
[navBar setDelegate:self];
[self.view addSubview:navBar];
[navBar setImage:[UIImage imageNamed:#"yourImageName"] NavTitle:#"yourTitle"];
}
- (void)popViewController:(CustomNavBar *)navBar1 {
// NSLog(#">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> delegate called");
[self.navigationController popViewControllerAnimated:YES];
}
-(void)btnleft_clicked:(CustomNavBar *)navBar1{
NSLog(#"\n\n btn Left Clicked InviteFriendsView");
}
NOTE: This is just an example , here implement your logic with your requirement.
Here you can also add 3rd button in middle and also define the method for called it in Delegate and also in this another .m file..
i hope this helpful for you...
i did this ,see below code
//IvisionApps Button
UIButton *ivisionButton= [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *ivisionButtonImage = [UIImage imageNamed:#"ivisionapps"];
UIImage *ivisionButtonImagePressed = [UIImage imageNamed:#"ivisionappsSelected"];
[ivisionButton setBackgroundImage:ivisionButtonImage forState:UIControlStateNormal];
[ivisionButton setBackgroundImage:ivisionButtonImagePressed forState:UIControlStateHighlighted];
[ivisionButton addTarget:self action:#selector(goIVisionApp) forControlEvents:UIControlEventTouchUpInside];
ivisionButton.frame = CGRectMake(-8, -20, 106, 38);
UIView *backButtonView = [[UIView alloc] initWithFrame:CGRectMake(-8, -20, 106, 38)];
backButtonView.bounds = CGRectOffset(backButtonView.bounds, -14, -7);
[backButtonView addSubview:ivisionButton];
UIBarButtonItem *backBarButton = [[UIBarButtonItem alloc] initWithCustomView:backButtonView];
self.navigationItem.rightBarButtonItem = backBarButton;
//Auxilaries Button
UIButton *auxiliariesButton= [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *auxiliariesButtonImage = [UIImage imageNamed:#"Auxiliaries"];
UIImage *auxiliariesButtonImagePressed = [UIImage imageNamed:#"AuxiliariesSelected"];
[auxiliariesButton setBackgroundImage:auxiliariesButtonImage forState:UIControlStateNormal];
[auxiliariesButton setBackgroundImage:auxiliariesButtonImagePressed forState:UIControlStateHighlighted];
[auxiliariesButton addTarget:self action:#selector(goBack) forControlEvents:UIControlEventTouchUpInside];
auxiliariesButton.frame = CGRectMake(-19, -20, 106, 38);
UIView *auxiliariesButtonView = [[UIView alloc] initWithFrame:CGRectMake(-19, -20, 106, 38)];
auxiliariesButtonView.bounds = CGRectOffset(auxiliariesButtonView.bounds, -14, -7);
[auxiliariesButtonView addSubview:auxiliariesButton];
UIBarButtonItem *auxiliariesBarButton = [[UIBarButtonItem alloc] initWithCustomView:auxiliariesButtonView];
self.navigationItem.leftBarButtonItem = auxiliariesBarButton;
//hide backBarButton of NavigationItem
[self.navigationItem setHidesBackButton:YES];

How to fire hightlight effect on UIBarButtonItem

When you tap on a UIBarButtonItem in a UIToolbar, there is a white glow effect.
Is there a possibility to fire an event to show this effect?
I don't want to press the button. Only the effect should be displayed. I want to visualize to the user, that there is new content behind this button.
Thanks for your help!
Heres the "highlight.png", I'm not kidding! (Though you may not seeing it on a white background.)
The following method assumes you are using the toolbarItems property of a navigation controller and that the button you want to highlight is the last item in that array. You can apply it to any toolbar, of course, and pick a different array index if necessary.
Right now this is not exactly perfect, because the animation moves the new button from the lower left of the screen. However, I think that can be turned off with a little effort.
Note that I used PeakJi's image.
I hope this works for you.
Enjoy,
Damien
- (void)highlightButton {
NSArray *originalFooterItems = self.toolbarItems;
NSMutableArray *footerItems = [originalFooterItems mutableCopy];
[footerItems removeLastObject];
NSString* pathToImageFile = [[NSBundle mainBundle] pathForResource:#"white_glow" ofType:#"png"];
UIImage* anImage = [UIImage imageWithContentsOfFile:pathToImageFile];
UIImageView *imageView = [[UIImageView alloc] initWithImage:anImage];
imageView.frame = CGRectMake(0, 0, 40, 40);
UIBarButtonItem *flashImage = [[UIBarButtonItem alloc] initWithCustomView:imageView];
[footerItems addObject:flashImage];
[UIView animateWithDuration:0.3
delay: 0.0
options: UIViewAnimationOptionCurveEaseOut
animations:^{
self.toolbarItems = footerItems; }
completion:^(BOOL finished){
[UIView animateWithDuration:.3
delay: 0.0
options:UIViewAnimationOptionCurveEaseIn
animations:^{
self.toolbarItems = originalFooterItems;
}
completion:nil];
}];
}
For Bar items
[(UIButton *)[[toolbarItems objectAtIndex:1] customView] setImage:[UIImage imageNamed:#"highlight.png"] forState:UIControlStateNormal];
In General - Assuming you have a button
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:#selector(someFunction:)
forControlEvents:UIControlEventTouchDown];
[button setTitle:#"Click here" forState:UIControlStateNormal];
button.frame = CGRectMake(0.0, 0.0, 100.0, 40.0);
[self.view addSubview:button];
you can at any given point, programmatically call this function:
[button setTitle:#"Look Here" forState:UIControlStateNormal];
or if you like to have an highlight image
btnImage = [UIImage imageNamed:#"highlight.png"];
[button setImage:btnImage forState:UIControlStateNormal];
A very simple alternative:
That said , you can also set the button like this:
- (void)highlightButton:(UIButton *)button {
[button setHighlighted:YES];
}
You can try to recreate a new bar button item with different style, and then reassign it back. My experiment was:
In viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
UIBarButtonItem *rightBtn = [[UIBarButtonItem alloc] initWithTitle:#"Custom"
style:UIBarButtonItemStylePlain
target:self
action:nil];
self.navigationItem.rightBarButtonItem = rightBtn;
[rightBtn release];
[self performSelector:#selector(highlight)
withObject:nil
afterDelay:2.0];
}
And in method highlight:
- (void) highlight{
UIBarButtonItem *rightBtn = [[UIBarButtonItem alloc] initWithTitle:#"Custom"
style:UIBarButtonItemStyleDone
target:self
action:nil];
self.navigationItem.rightBarButtonItem = rightBtn;
[rightBtn release];
}
Your implementation might be different than mine, but as long as you are fine with reassigning the bar button, I think it'll work as expected. Good luck :)
If you have a category:
#define HIGHLIGHT_TIME 0.5f
#interface UIButton (Highlight)
- (void)highlight;
#end
#implementation UIButton (Highlight)
- (void)highlight {
UIButton *overlayButton = [UIButton buttonWithType:UIButtonTypeCustom];
overlayButton.frame = self.frame;
overlayButton.showsTouchWhenHighlighted = YES;
[self.superview addSubview:overlayButton];
overlayButton.highlighted = YES;
[self performSelector:#selector(hideOverlayButton:) withObject:overlayButton afterDelay:HIGHLIGHT_TIME];
}
- (void)hideOverlayButton:(UIButton *)overlayButton {
overlayButton.highlighted = NO;
[overlayButton removeFromSuperview];
}
#end
Then you need code like this…
UIBarButtonItem *addButton = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(insertNewObject:)] autorelease];
self.navigationItem.rightBarButtonItem = addButton;
[self.navigationController.navigationBar.subviews.lastObject performSelector:#selector(highlight) withObject:nil afterDelay:2];
…to highlight the button in the navigation bar after 2 seconds.
A simple ay is to init your UIBarButtonItem with a CustomView (UIBUtton)
UIButton *favButton = [UIButton buttonWithType:UIButtonTypeCustom];
[favButton setFrame:CGRectMake(0.0, 100.0, 50.0, 30.0)];
[favButton setBackgroundImage:[UIImage imageNamed:#"bouton_black_normal.png"]
forState:UIControlStateNormal];
[favButton setBackgroundImage:[UIImage imageNamed:#"bouton_black_hightlight.png"]
forState:UIControlStateHighlighted];
[favButton setTitle:#"Add" forState:UIControlStateNormal];
[favButton setTitle:#"Add" forState:UIControlStateHighlighted];
[favButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[favButton setTitleColor:[UIColor whiteColor] forState:UIControlStateHighlighted];
[[favButton titleLabel] setFont:[UIFont boldSystemFontOfSize:13]];
[favButton addTarget:self action:#selector(doSomething)
forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithCustomView:favButton];

Customization of UINavigationBar and the back button

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;
}

Forward event from custom UIControl subclass

My custom subclass extend UIControl (EditableImageView)
Basically it contains 3 subviews:
UIButton (UIButtonTypeCustom)
UIImageView
UILabel
All the class works great but now I want to connect some events generated from this class to another. In particular when the button is pressed I want to forward the event to the owner viewcontroller so that I can handle the event. The problem is that I can't figure out how to implement this behaviour.
Within EditableImageView I can catch the touch event using [button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside] but I don't know how to forward it inside of the buttonPressed selector.
I also tried to implement touchesBegan but it seems never called...
I'd like to capture the button press event from the viewcontroller in this way:
- (void)viewDidLoad {
[super viewDidLoad];
self.imageButton = [[EditableImageView alloc] initWithFrame:CGRectMake(50.0f, 50.0f, 80.0f, 80.0f)];
[imageButton addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:imageButton];
[imageButton setEditing:NO];
}
This is my UIControl subclass initialization method:
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self setBackgroundColor:[UIColor clearColor]];
button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0.0f, 0.0f, frame.size.width, frame.size.height);
[button setImage:[UIImage imageNamed:#"nene_70x70.png"] forState:UIControlStateNormal];
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:button];
transparentLabelBackground = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"editLabelBackground.png"]];
transparentLabelBackground.hidden = YES;
[self addSubview:transparentLabelBackground];
// create edit status label
editLabel = [[UILabel alloc] initWithFrame:CGRectZero];
editLabel.hidden = YES;
editLabel.userInteractionEnabled = NO; // without this assignment the button will not be clickable
editLabel.textColor = [UIColor whiteColor];
editLabel.backgroundColor = [UIColor clearColor];
editLabel.textAlignment = UITextAlignmentLeft;
UIFont *labelFont = [UIFont systemFontOfSize:16.0];
editLabel.font = labelFont;
editLabel.text = #"edit";
labelSize = [#"edit" sizeWithFont:labelFont];
[self addSubview:editLabel];
}
return self;
}
Thanks.
I solved in this way:
EditableImageView.h:
#interface EditableImageView : UIControl {
UIButton *button;
UIImageView *transparentLabelBackground;
UILabel *editLabel;
CGSize labelSize;
BOOL editing;
}
#property (nonatomic, retain) UIButton *button;
#property (nonatomic, retain) UILabel *editLabel;
#property (nonatomic, retain) UIImageView *transparentLabelBackground;
#property (nonatomic, getter=isEditing) BOOL editing;
- (void)buttonPressed:(id)sender;
#end
EditableImageView.m:
(id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self setBackgroundColor:[UIColor clearColor]];
button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0.0f, 0.0f, frame.size.width, frame.size.height);
[button setImage:[UIImage imageNamed:#"nene_70x70.png"] forState:UIControlStateNormal];
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
.......
}
}
- (void)buttonPressed:(id)sender {
[self sendActionsForControlEvents:UIControlEventTouchUpInside];
}
MyController.m:
- (void)viewDidLoad {
[super viewDidLoad];
self.imageButton = [[EditableImageView alloc] initWithFrame:CGRectMake(50.0f, 50.0f, 80.0f, 80.0f)];
[imageButton addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:imageButton];
}
- (void)buttonPressed:(id)sender {
NSLog(#"buttonPressed!");
}

Custom UIButton for Iphone

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];