How do I go about adding actions to buttons that are created in a UIView subclass?
Here is my code. This is my first time writing my views purely programmatically in a UIView subclass. I have create the "directions" button as follows:
directionsButton = [self buttonWithTitle:#"Directions" target:self selector:#selector(getDirections:) frame:directionsFrame image:buttonImage insertImage:directionsIcon];
Now how can I add the "getDirections" selector in my view controller? The following UIView subclass is added as a subview of BookViewController
#import "BookView.h"
#define GRAY_BOTTOM 44
#define PADDING 5
#define THUMB_WIDTH 50
#define THUMB_HEIGHT 43
#define DIRECTIONS_BUTTON_WIDTH 94
#define BUTTON_HEIGHT 34
#define BUTTON_VERTICAL_INSET 2
static NSArray* grayBottomButtons = nil;
#interface BookView (PrivateMethods)
- (void)setupSubviewsWithContentFrame:(CGRect)frameRect;
- (UIButton *)buttonWithTitle:(NSString *)title target:(id)target selector:(SEL)inSelector frame:(CGRect)frame image:(UIImage*)image insertImage:(UIImage*)insertImage;
#end
#implementation BookView
// #synthesize delegate;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setupSubviewsWithContentFrame:frame];
self.backgroundColor = [UIColor clearColor]; // Make sure clear Background
self.opaque = NO;
}
return self;
}
- (void)setupSubviewsWithContentFrame:(CGRect)frameRect {
// Setup views
// Create frame for white background
CGRect frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
WhiteRoundedView *whiteBg = [[WhiteRoundedView alloc] initWithFrame:frame];
// Create frame for gray bottom view
CGRect gFrame = CGRectMake(0, (self.frame.size.height - GRAY_BOTTOM), self.frame.size.width, GRAY_BOTTOM);
GrayBottomView *grayBg = [[GrayBottomView alloc] initWithFrame:gFrame];
// Create salon thumbnail view
UIImageView *salonThumb = [[UIImageView alloc] initWithFrame:CGRectMake(PADDING, PADDING, THUMB_WIDTH, THUMB_HEIGHT)];
// Set salonThumb image
salonThumb.image = [UIImage imageNamed:#"SalonThumb.png"];
// Set salonName UILabel
UILabel *salonName = [[UILabel alloc] initWithFrame:CGRectMake((PADDING*2 + THUMB_WIDTH), PADDING, 200, 15)];
// Set text
salonName.text = #"Salon Aria";
// Set font
salonName.font = [UIFont fontWithName:#"PTSans-Bold" size:15.0];
// Set Alignment
salonName.textAlignment = UITextAlignmentLeft;
// Set font color
salonName.textColor = [UIColor colorWithRed:0.0f/255.0 green:0.0f/255.0 blue:0.0f/255.0 alpha:1.0];
// Set salonAddressLineOne UILabel (Line One)
UILabel *salonAddressLineOne = [[UILabel alloc] initWithFrame:CGRectMake((PADDING*2 + THUMB_WIDTH), (PADDING + 15), 140, 13)];
// Set text
salonAddressLineOne.text = #"6325 Main St, Suite 140";
// Set font
salonAddressLineOne.font = [UIFont fontWithName:#"PTSans-Regular" size:13.0];
// Set Alignment
salonAddressLineOne.textAlignment = UITextAlignmentLeft;
// Set font color
salonAddressLineOne.textColor = [UIColor colorWithRed:40.0f/255.0 green:40.0f/255.0 blue:40.0f/255.0 alpha:1.0];
// Set salonAddressLineTwo UILabel (Line Two)
UILabel *salonAddressLineTwo = [[UILabel alloc] initWithFrame:CGRectMake((PADDING*2 + THUMB_WIDTH), (PADDING + 28), 140, 13)];
// Set text
salonAddressLineTwo.text = #"Woodridge, IL 60517";
// Set font
salonAddressLineTwo.font = [UIFont fontWithName:#"PTSans-Regular" size:13.0];
// Set font color
salonAddressLineTwo.textColor = [UIColor colorWithRed:40.0f/255.0 green:40.0f/255.0 blue:40.0f/255.0 alpha:1.0];
// Set Alignment
salonAddressLineTwo.textAlignment = UITextAlignmentLeft;
// Set the background image with stretchable type for all buttons on this view
UIImage *buttonImage = [[UIImage imageNamed:#"UIButton.png"] stretchableImageWithLeftCapWidth:2 topCapHeight:2];
// Set the insert image (directions icon)
UIImage *directionsIcon = [[UIImage imageNamed:#"DirectionsIcon.png"] stretchableImageWithLeftCapWidth:2 topCapHeight:2];
// Set the directions button frame
CGRect directionsFrame = CGRectMake(self.frame.size.width - PADDING - DIRECTIONS_BUTTON_WIDTH, PADDING, DIRECTIONS_BUTTON_WIDTH, BUTTON_HEIGHT);
// Add the button
directionsButton = [self buttonWithTitle:#"Directions" target:self selector:#selector(getDirections:) frame:directionsFrame image:buttonImage insertImage:directionsIcon];
// Create the salonMap with frame
salonMap = [[MKMapView alloc] initWithFrame:
CGRectMake(PADDING, (PADDING*2 + THUMB_HEIGHT), (self.frame.size.width - PADDING*2), (self.frame.size.height - THUMB_HEIGHT - PADDING*3 - GRAY_BOTTOM))];
// Add view in proper order and location
[self addSubview:whiteBg];
[whiteBg addSubview:grayBg];
[whiteBg addSubview:salonThumb];
[whiteBg addSubview:salonName];
[whiteBg addSubview:salonAddressLineOne];
[whiteBg addSubview:salonAddressLineTwo];
[whiteBg addSubview:directionsButton];
[whiteBg addSubview:salonMap];
[self setNeedsDisplay];
}
- (UIButton *)buttonWithTitle:(NSString *)title target:(id)target selector:(SEL)inSelector frame:(CGRect)frame image:(UIImage*)image insertImage:(UIImage*)insertImage
{
// Create button
UIButton *button = [[UIButton alloc] initWithFrame:frame];
// Set button content alignment
button.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
// Set button title
[button setTitle:title forState:UIControlStateNormal & UIControlStateHighlighted & UIControlStateSelected];
// Set button title color
[button setTitleColor:[UIColor colorWithRed:91.0f/255.0 green:82.0f/255.0 blue:82.0f/255.0 alpha:1.0] forState:UIControlStateNormal & UIControlStateHighlighted & UIControlStateSelected];
// Add the background image
[button setBackgroundImage:image forState:UIControlStateNormal];
// Add Events
[button addTarget:target action:inSelector forControlEvents:UIControlEventTouchUpInside];
// in case the parent view draws with a custom color or gradient, use a transparent color
[button setBackgroundColor:[UIColor clearColor]];
// Set titleShadowColor this way (apparently, titleLabel.shadowcolor does not work)
[button setTitleShadowColor:[UIColor colorWithRed:255.0f/255.0 green:255.0f/255.0 blue:255.0f/255.0 alpha:.75] forState:UIControlStateNormal & UIControlStateHighlighted & UIControlStateSelected];
// Set button titleLabel properties
button.titleLabel.font = [UIFont fontWithName:#"PTSans-Bold" size:13.0];
button.titleLabel.shadowOffset = CGSizeMake(1, 1);
// If there is an insertImage icon
if(insertImage != nil)
{
// padding between image and text
int seperate = 6;
// Image and title frame (used to center text/image)
int width = (button.titleLabel.frame.size.width + insertImage.size.width + seperate);
int buttonWidth = button.frame.size.width;
int xPadding = (buttonWidth - width)/2;
int yPadding = (button.frame.size.height - insertImage.size.height)/2;
// Create an image view for the image (standard icon is 12x13)
UIImageView *insertImageView = [[UIImageView alloc] initWithFrame:CGRectMake(xPadding, yPadding, insertImage.size.width, insertImage.size.height)];
// add the insertImage to the view
[insertImageView setImage:insertImage];
// add the insertImageView to the button
[button addSubview:insertImageView];
// Add offset with title
button.titleEdgeInsets = UIEdgeInsetsMake(BUTTON_VERTICAL_INSET, insertImage.size.width + seperate, 0, 0);
}
else
{
// No image so no horizontal offset but PTSans font needs a 2 vertical offset
button.titleEdgeInsets = UIEdgeInsetsMake(BUTTON_VERTICAL_INSET, 0, 0, 0);
}
return button;
}
#end
From the view controller, for each button in the view do something like:
[button addTarget:self action:#selector(aMethod:) forControlEvents:UIControlEventTouchUpInside];
Alternatively you can set up the connection within Interface Builder by ctrl-dragging from the button to the header file of the file owner (the view controller). This will ask you to define a method name, and link it all up for you.
Related
I'm making an app. My app is based off this sample project. https://github.com/yeahdongcn/RSCircaPageControl
In the app there is a view. On the view, there is a scroll view (UIScrollView *scrollView) which allows to 10 "pages" of content. Within each page, there is another scroll view (UIScrollView *sv) which is a subview of *scrollView.
On SV, I then added a button called UIButton *button. When I attempt to change the button's images after a time of "two minutes," nothing happens. This is because there are 10 buttons. I need to change the image of the button on only one of the pages. Not all of them.
Something tells me it needs "object at index" or something to specify which button on which page I want to change.
The code is below! Thanks guys!
- (void)viewDidLoad
{
[super viewDidLoad];
self.clipView = [[RSView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
self.clipView.clipsToBounds = YES;
[self.view addSubview:self.clipView];
self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.clipView.bounds.size.width, kScrollViewHeight)];
self.scrollView.delegate = self;
self.scrollView.clipsToBounds = NO;
self.scrollView.pagingEnabled = YES;
self.scrollView.showsHorizontalScrollIndicator = NO;
self.scrollView.showsVerticalScrollIndicator = NO;
self.scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[self.view addSubview:self.scrollView];
self.clipView.scrollView = self.scrollView;
self.pageControl = [[RSCircaPageControl alloc] initWithNumberOfPages:10];
CGRect frame = self.pageControl.frame;
frame.origin.x = self.view.bounds.size.width - frame.size.width - 10;
frame.origin.y = roundf((self.view.bounds.size.height - frame.size.height) / 2.);
self.pageControl.frame = frame;
self.pageControl.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
[self.pageControl setCurrentPage:0 usingScroller:NO];
[self.view addSubview:self.pageControl];
CGFloat currentY = 0;
for (int i = 0; i < 10; i++) {
UIScrollView *sv = [[UIScrollView alloc] initWithFrame:CGRectMake(0, currentY, self.scrollView.bounds.size.width, kScrollViewHeight)];
sv.tag = kScrollViewTagBase + i;
sv.delegate = self;
sv.autoresizingMask = UIViewAutoresizingFlexibleWidth;
sv.backgroundColor = [UIColor colorWithRed:(arc4random() % 257) / 256. green:(arc4random() % 257) / 256. blue:(arc4random() % 257) / 256. alpha:1];
///here's the buttton!!
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage*normal = [UIImage imageNamed:#"girl.jpg"];
UIImage*selected = [UIImage imageNamed:#"girl2.jpg"];
button.frame = CGRectMake(100, 100, 50,50));
[button setImage:normal forState:UIControlStateNormal];
[button setImage:selected forState:UIControlStateHighlighted];
button.contentMode = UIViewContentModeScaleAspectFit;
[button addTarget:self
action:#selector(myButtonPressed:)
forControlEvents:UIControlEventTouchDown];
[sv addSubview:button]; //notice that the button is added as a subview of SV
[self.scrollView addSubview:sv]; // notice that SV is a subview of the scrollView.
if (i == 2 || i == 6) {
sv.contentSize = CGSizeMake(sv.contentSize.width, kScrollViewContentHeight);
}
currentY += kScrollViewHeight;
}
self.scrollView.contentSize = CGSizeMake(self.scrollView.contentSize.width, currentY);
[self performSelector:changeButtomImages withObject:nil afterDelay:TwoMinutes];
}
- (void)changeButtonImages {
UIImage*normal2 = [UIImage imageNamed:#"boy.jpg"];
UIImage*selected2 = [UIImage imageNamed:#"boy2.jpg"];
[button setImage:normal2 forState:UIControlStateNormal];
[button setImage:selected2 forState:UIControlStateHighlighted];
}
Kyle
for setting button image in a normal state the parameter to pass forState: is UIControlStateNormal not UIControlStateHighlighted
So, in changeButtonImages you are changing the the image for the iVar "button", but you are never actually assigning anything to that button var. In your for loop in viewDidLoad, you are creating a local variable of UIButton called button. Maybe something like this?
- (void)myButtonPressed:(id)sender
{
UIButton *button = (UIButton *)sender;
UIImage*normal2 = [UIImage imageNamed:#"boy.jpg"];
UIImage*selected2 = [UIImage imageNamed:#"boy2.jpg"];
[button setImage:normal2 forState:UIControlStateNormal];
[button setImage:selected2 forState:UIControlStateHighlighted];
}
I have created a subclass of the UIButton class. I want to change its background color upon the creation. How do I write the constructor method?
-(id)initWithFrame :(CGRect)frame{
if(self = [super init]) {
// The default size for the save button is 49x30 pixels
self.frame = frame;//CGRectMake(0, 0, 60.0, 34.0);
// Center the text vertically and horizontally
self.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
self.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
UIImage *image = [UIImage imageNamed:#"image.png"];
[self setBackgroundImage:image forState:UIControlStateNormal];
[self setBackgroundColor:[UIColor blueColor]];
// Set the font properties
// [self setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];
self.titleLabel.font = [UIFont boldSystemFontOfSize:12];
}
return self;
}
I have created UIToolbar control.which is added as setInputAccessoryView to one UITextField Control.Which works fine. the tollbar comes up with uikeyboard when tapping UITextField.Up to this no issues.
When i placed one button, when tapping on it i want to hide the keyboard and only want to display the toolbar.
This is not happening.the toolbar is getting hidden.
Please let me know , what is the problem/ reason in the code.
Thanks for your time.
- (void)viewDidLoad {
[super viewDidLoad];
//
myToolbar = [[UIToolbar alloc] init];
[myToolbar sizeToFit];
myToolbar.frame = CGRectMake(0,198, 320, 35);
myToolbar.barStyle = UIBarStyleBlackTranslucent;
[self.view addSubview:myToolbar];
UIImage *image = [UIImage imageNamed:#"orangebuttonsmall.png"];
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeCustom];
aButton.frame = CGRectMake(0, 100, image.size.width, 25 );
aButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
[aButton setTitle:#"Tap" forState:UIControlStateNormal];
[aButton setBackgroundImage: image forState:UIControlStateNormal];
[aButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
aButton.titleLabel.font = [UIFont boldSystemFontOfSize:10];
[aButton addTarget:self action:#selector(aCenterBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:aButton];
myToField = [[UITextField alloc] init];
myToField.frame = CGRectMake(0, 0, 320, 48);
myToField.textColor = [UIColor blackColor]; //text color
myToField.font = [UIFont systemFontOfSize:17.0]; //font size
myToField.placeholder = #"To:"; //place holder
myToField.backgroundColor = [UIColor whiteColor]; //background color
myToField.autocorrectionType = UITextAutocorrectionTypeNo; // no auto correction support
myToField.keyboardType = UIKeyboardTypePhonePad; // type of the keyboard
myToField.returnKeyType = UIReturnKeyDone; // type of the return key
myToField.clearButtonMode = UITextFieldViewModeWhileEditing;
[myToField setInputAccessoryView:myToolbar];
myToField.textAlignment = UITextAlignmentLeft;
[myToField setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter];
myToField.rightViewMode=UITextFieldViewModeAlways;
// has a clear 'x' button to the right
myToField.delegate = self;
[myToField becomeFirstResponder];
[self.view addSubview:myToField];
}
-(void)aCenterBtnClicked:(id)sender{
[myToField resignFirstResponder];
myToolbar.frame = CGRectMake(0,198, 320, 35);
myToolbar.barStyle = UIBarStyleBlackTranslucent;
[self.view addSubview:myToolbar];
}
inputAccessoryViews are placed as a subview on the UIKeyboard, if you hide the keyboard, it will hide the inputAccessoryView. Try adding the toolbar as a subview of self.view and animate it's position up when the keyboard is displayed by subscribing to the UIKeyboardWillShow notification and pulling the animation duration from the userInfo.
You try for static toolbar i think that will be easy for you.I am not done before remove from setinputview because there is no method for remove set input view.
My UIButton doesn't respond. I think it is behind the UIView or that it is not the first responder. I made a custom view which subclass is MKAnnotationView. Maybe this is a part of the problem. I also tried to use userInteractionEnabled, but no luck. Anyone had the same issue?
- (id)initWithAnnotation:(id)annotation reuseIdentifier:(NSString *)reuseIdentifier{
self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier];
// Create selected and un-selected pin images
_normalPin = [UIImage imageNamed:#"map_pin.png"];
_selectedPin = [UIImage imageNamed:#"selected_map_pin.png"];
// Set current pin to unselected image
self.image = _normalPin;
// cast annotation an our expected BLAnnotation
Annotation *blAnnotation = (Annotation *)annotation;
// create title label and size to text
_titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 5, 280, 20)];
_titleLabel.text = blAnnotation.title;
_titleLabel.textAlignment = UITextAlignmentLeft;
_titleLabel.font = [UIFont fontWithName:#"HelveticaNeue-Bold" size:13];
_titleLabel.textColor = [UIColor whiteColor];
_titleLabel.shadowColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:.7];
_titleLabel.shadowOffset = CGSizeMake(0, -1.0);
_titleLabel.backgroundColor = [UIColor clearColor];
_titleLabel.lineBreakMode = UILineBreakModeWordWrap;
_titleLabel.numberOfLines = 3;
CGSize titleLabelSize = [blAnnotation.title sizeWithFont: _titleLabel.font constrainedToSize: CGSizeMake(280, 600) lineBreakMode: _titleLabel.lineBreakMode];
_titleLabel.frame = CGRectMake(_titleLabel.frame.origin.x, _titleLabel.frame.origin.y, 280, titleLabelSize.height);
// create subtitle label and size to text
_subtitleLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, _titleLabel.frame.size.height + 8, 280, 20)];
_subtitleLabel.text = blAnnotation.subtitle;
_subtitleLabel.textAlignment = UITextAlignmentLeft;
_subtitleLabel.font = [UIFont fontWithName:#"HelveticaNeue" size:11];
_subtitleLabel.textColor = [UIColor whiteColor];
_subtitleLabel.shadowColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:.7];
_subtitleLabel.shadowOffset = CGSizeMake(0, -1.0);
_subtitleLabel.backgroundColor = [UIColor clearColor];
_subtitleLabel.lineBreakMode = UILineBreakModeWordWrap;
_subtitleLabel.numberOfLines = 4;
CGSize subtitleLabelSize = [blAnnotation.subtitle sizeWithFont: _subtitleLabel.font constrainedToSize: CGSizeMake(235, 600) lineBreakMode: _subtitleLabel.lineBreakMode];
_subtitleLabel.frame = CGRectMake(_subtitleLabel.frame.origin.x, _subtitleLabel.frame.origin.y, subtitleLabelSize.width, subtitleLabelSize.height);
// create custom button
_infoButton = [UIButton buttonWithType:UIButtonTypeCustom];
_infoButton.frame = CGRectMake(0, _titleLabel.frame.size.height + _subtitleLabel.frame.size.height + 80, 175, 50);
//_infoButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
//_infoButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
//[_infoButton setImage:[UIImage imageNamed:#"more_info.png"] forState:UIControlStateNormal];
[_infoButton addTarget:self action:#selector(pressButton:) forControlEvents:UIControlEventTouchUpInside];
// create callout view to be shown once a annotation view is selected
_calloutView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, _titleLabel.frame.size.height + _subtitleLabel.frame.size.height + _infoButton.frame.size.height + 5)];
_calloutView.hidden = YES;
_calloutView.userInteractionEnabled = YES;
[self addSubview:_calloutView];
// create rounded rect background and size to text
UIImageView *backgroundRect = [[UIImageView alloc] initWithFrame: CGRectMake(0, 0, _calloutView.frame.size.width, _calloutView.frame.size.height)];
//[backgroundRect setAlpha:0.8];
//[backgroundRect setOpaque:NO];
[backgroundRect.image drawInRect:_calloutView.frame];
UIGraphicsBeginImageContext(backgroundRect.frame.size);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGRect frame = _calloutView.bounds;
[[UIColor colorWithRed:.2 green:.2 blue:.2 alpha:1] set];
CGPathRef roundedRectPath = [self roundedRectPath:frame radius:5];
CGContextAddPath(ctx, roundedRectPath);
CGContextFillPath(ctx);
CGPathRelease(roundedRectPath);
backgroundRect.userInteractionEnabled = YES;
backgroundRect.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[_calloutView addSubview:backgroundRect];
[_calloutView addSubview:_titleLabel];
[_calloutView addSubview:_subtitleLabel];
[_calloutView addSubview:_infoButton];
// position callout above pin
_calloutView.frame = CGRectMake(-140, -_calloutView.frame.size.height+10, _calloutView.frame.size.width, _calloutView.frame.size.height);
backgroundRect = nil;
return self;
}
My guess is that your button is pointing to itself as the target. If the button is not the first responder and it is tapped, its target function is not called in the above scenario. I fixed my similar issue by using lazy var to declare the UIButton in Swift 4 Xcode 9, pointing the target to the parent view / view controller.
// Sets target to parent view or view controller
// someFunction is called even if the button is not the first responder when tapped
lazy var nextCreateButton: UIButton = {
let button = UIButton(type: .system)
button.addTarget(self, action: #selector(someFunction), for: .touchUpInside)
return button
}()
// Sets target to the button itself
// someFunction is not called when the button is not the first responder
let nextCreateButton: UIButton = {
let button = UIButton(type: .system)
button.addTarget(self, action: #selector(someFunction), for: .touchUpInside)
return button
}()
Try using [self addSubview:_calloutView] after you add your button and your lables to *_calloutView* as subviews, not before.
Let me know how it turns out
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;
}