Custom button in iOS with rounded rect stroke, icon and label - ios

I would like to recreate this button using code so it's a reusable object, and you can set the minimum width, height, or it stretches to fit the icon and label. Throughout the app, we'll reuse the button in several areas and it will include a thin rounded rect stroke, a background color, an icon (trans PNG), and a label. We want to make the background color, and stroke color configurable so we can toggle the button on/off.
EDIT: Almost working code but the text label block is white and need to resize image to fit in frame and both to be centered.
Custom button code:
#import "CustomButton.h"
#implementation CustomButton
- (id)initWithFrame:(CGRect)frame image:(NSString *)image title:(NSString *)title background:(UIColor *)background border:(UIColor *)border
{
self = [super initWithFrame:frame];
if (self)
{
self = [UIButton buttonWithType:UIButtonTypeCustom];
CALayer *layer = [self layer];
self.contentVerticalAlignment = UIControlContentVerticalAlignmentBottom;
self.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
// background
if (background) {
layer.backgroundColor = (__bridge CGColorRef)(background);
} else {
layer.backgroundColor = [[UIColor darkGrayColor] CGColor];
}
// border
if (border) {
layer.borderColor = (__bridge CGColorRef) (border);
} else {
layer.borderColor = [[UIColor lightGrayColor] CGColor];
}
layer.cornerRadius = 2.0f;
layer.borderWidth = 0.5f;
// icon
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:image]];
[self addSubview:imageView];
// text label
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 25, 55, 15)];
titleLabel.font = [[UIFont alloc] fontWithSize:7.00];
titleLabel.text = title;
[self addSubview:titleLabel];
[self setFrame:frame];
}
return self;
}
#end
EDIT: Updated code block above and got button to appear using the following code in the respective view in viewController:
CGRect buttonFrame = CGRectMake(125, 3, 52, 37);
CustomButton *btnNearby = [[CustomButton alloc] initWithFrame:buttonFrame image:#"map.png" title:#"NEARBY" background:nil border:nil];
[myCustomView addSubview:btnNearby];
The custom button appears but still not formatted properly.
Here is an example icon (white PNG w/ trans) that should appear in center of button.
Summary of desired functionality:
1) reusable button
2) can have min width/height or override to match width of label and height of image + label
3) has configurable stroke color
4) matches button icon above with stroke + icon + label + background color
5) can change the border color to toggle on/off

You could try something like this:
#import <QuartzCore/QuartzCore.h>
#implementation CustomButton
- (id)initWithFrame:(CGRect)frame andImageName:(NSString*)filename ofType:(NSString*)type
{
self = [super initWithFrame:frame];
if (self)
{
self = [UIButton buttonWithType:UIButtonTypeCustom];
CALayer *layer = [self layer];
layer.borderColor = [[UIColor blueColor] CGColor];
layer.cornerRadius = 4.0f;
layer.borderWidth = 2.0f;
UIImage* img = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:filename ofType:type]];
UIImageView* imgView = [[UIImageView alloc] initWithImage:img];
[imgView setFrame:CGRectMake(0, 0, img.size.width, img.size.height)];
[self addSubview:imgView];
[self setFrame:frame];
}
return self;
}
- (void)switchColor
{
CALayer *layer = [self layer];
if(buttonIsOn)
layer.borderColor = [[UIColor blueColor] CGColor];
else
layer.borderColor = [[UIColor grayColor] CGColor];
}
#end
And everytime you use this button, just use:
CustomButton* cusButton = [[CustomButton alloc] initWithFrame:someFrame];
In order to alternate the stroke color, just call switchColor in the first line of cusButton's target method and you should be fine.

I was able to solve this problem and I'm sure it can be refined further but the button now appears as desired in question. See snap of end result, and working code below hopefully to help others.
Working screenshot:
Working code:
CustomButton.h
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#interface CustomButton : UIButton
- (id)initWithFrame:(CGRect)frame image:(NSString *)image title:(NSString *)title background:(UIColor *)background border:(UIColor *)border;
#end
CustomButton.m
#import "CustomButton.h"
#implementation CustomButton
- (id)initWithFrame:(CGRect)frame image:(NSString *)image title:(NSString *)title background:(UIColor *)background border:(UIColor *)border
{
self = [super initWithFrame:frame];
if (self)
{
self = [UIButton buttonWithType:UIButtonTypeCustom];
CALayer *layer = [self layer];
// background
if (background) {
layer.backgroundColor = (__bridge CGColorRef)(background);
} else {
layer.backgroundColor = [[UIColor darkGrayColor] CGColor];
}
// border
if (border) {
layer.borderColor = (__bridge CGColorRef)(border);
} else {
layer.borderColor = [[UIColor lightGrayColor] CGColor];
}
layer.cornerRadius = 2.0f;
layer.borderWidth = 0.5f;
// icon
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(14,3,20,19)];
imageView.image = [UIImage imageNamed:image];
imageView.contentMode = UIViewContentModeScaleAspectFit;
[self addSubview:imageView];
// text label
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 20, 50, 14)];
titleLabel.opaque = NO;
titleLabel.numberOfLines = 1;
titleLabel.textAlignment = UITextAlignmentCenter;
titleLabel.font = [UIFont systemFontOfSize:7.00];
titleLabel.textColor = [UIColor whiteColor];
titleLabel.backgroundColor = [UIColor clearColor];
titleLabel.text = title;
[self addSubview:titleLabel];
[self setFrame:frame];
}
return self;
}
#end
Instantiated the button on a UIImage layer that had segue to the View Controller:
// Add custom button to image view background layer
CGRect buttonFrame = CGRectMake(125, 3, 50, 35);
CustomButton *btnNearby = [[CustomButton alloc] initWithFrame:buttonFrame image:#"map.png" title:#"NEARBY" background:nil border:nil];
[myCustomView addSubview:btnNearby];

Related

Setting text of a UITextField does not update UI, until it gets focus | iOS

I have a few custom UITextFields inside a scrollview. I'm setting textfield's text programmatically. But the text is not visible until it gets focus
This is how I set the text:
[self.textfield setText:#"+998 "];
This is my custom textfield:
#implementation BottomBorderedTF{
CALayer* bottomLine;
CGColorRef borderColor;
}
- (void)awakeFromNib{
[super awakeFromNib];
borderColor = [UIColor colorNamed:#"ofb_blue"].CGColor;
}
- (void)layoutSubviews{
bottomLine = [[CALayer alloc] init];
borderColor = [UIColor colorNamed:#"ofb_blue"].CGColor;
bottomLine.frame = CGRectMake(0.0, self.frame.size.height - 1, self.frame.size.width, 1.0);
bottomLine.backgroundColor = borderColor;
self.borderStyle = UITextBorderStyleNone;
[self.layer addSublayer:bottomLine];
}
- (void)showError:(BOOL)hasError{
if (hasError) {
bottomLine.backgroundColor = UIColor.redColor.CGColor;
} else {
bottomLine.backgroundColor = borderColor;
}
}
#end

How do I crop a MKMapView (or any UIView) into a custom shape?

I'm trying to size an MKMapView in the following way:
Elements should be able to appear behind the arc at the top, so it appears that the view is not square. I know this should be possible with CALayer, but perhaps someone has done it before?
This should be quite possible if you put your MKMapView within a UIView, then apply a mask to that.
Here's a very (!) basic example:
All I've done is put my map in a UIView called "mapContainer" and added a mask to it using this:
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
CGRect rect = CGRectInset(self.view.frame, 70, 70);
UIView* newView = [[UIView alloc] initWithFrame:rect];
newView.layer.cornerRadius = 55.0;
newView.backgroundColor = [UIColor redColor];
self.mapContainer.layer.mask = newView.layer;
}
And you could add a border to it...
..with a few more lines...
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
CGRect rect = CGRectInset(self.view.frame, 70, 70);
UIView* newView = [[UIView alloc] initWithFrame:rect];
newView.layer.cornerRadius = 55.0;
newView.backgroundColor = [UIColor redColor];
UIView* borderView = [[UIView alloc] initWithFrame:rect];
borderView.backgroundColor = [UIColor clearColor];
borderView.layer.cornerRadius = 55.0;
borderView.layer.borderWidth = 3.0;
borderView.layer.borderColor = [[UIColor redColor] CGColor];
[self.mapContainer addSubview:borderView];
[self.mapContainer bringSubviewToFront:borderView];
self.mapContainer.layer.mask = newView.layer;
}
I hope this points you in the right direction.
Unlike Apple Maps.
;-)

How can I build a transparent view with shadow outside in iOS?

I want to build a totally transparent view, the backgroundColor maybe clearColor. Inside this view I want to put a small image. And in the four sides of this transparent view, I want to see the effect of shadow. The shadow must be totally outside the view. I know that I must override the drawRect method in UIView, but don't know how to do this.
try this....
UIView *shadowView = [[UIView alloc] initWithFrame:CGRectMake(50.0, 100.0, 100.0, 100.0)];
shadowView.layer.cornerRadius = 15.0;
CALayer *layer = shadowView.layer;
layer.shadowOpacity = 1.0;
layer.shadowColor = [[UIColor blackColor] CGColor];
layer.shadowOffset = CGSizeMake(0,0);
layer.shadowRadius = 15;
[self.view addSubview:shadowView];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, 50.0, 50.0)];
[imageView setImage:[UIImage imageNamed:#"icon.png"]];
[shadowView addSubview:imageView];
What is the problem with doing something like this?
#import <QuartzCore/QuartzCore.h> // at the top of the file
UIView *transparentView = [[UIView alloc] initWithFrame:CGRectMake(50,50,200,200)];
transparentView.backgroundColor = [UIColor greenColor];
transparentView.alpha = 0.5f;
transparentView.clipsToBounds = NO;
transparentView.layer.shadowColor = [UIColor blackColor].CGColor;
transparentView.layer.shadowOpacity = 1;
transparentView.layer.shadowRadius = 1;
UIImageView *imageView = [[]UIImageView alloc] initWithFrame:CGRectMake(50, 50, 50, 50)];
imageView.image = [UIImage imageNamed:#"IMAGE NAME"];
[transparentView addSubview:imageView];
As you can see, based on your description, no drawRect: required, unless for some reason you want to draw the shadow manually, but there isn't a reason to.

Changing Only Part of a Custom UITableViewCell Selected Background Color

I have a custom cell that I am controlling the color of when it is selected, ie the example code below:
UIView *selectedBackground = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 600, 600)];
[selectedBackground setBackgroundColor:[UIColor selectedCellColor]];
self.selectedBackgroundView = selectedBackground;
This works, however I would only like to have part of the cell change colors when selected. My custom cell is broken down into many different subviews, and I have it sectioned out where I would be able to define the specific view that I would like to change colors for.
How can I control the selectedBackgroundView, or use a different method, to have the background color change encompass a single subview in my cell?
Ya you are in the rite way,by subclassing the UITableView cell
hear is the sample code that you may find the answer for your question :)
//in subclassed cell class
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
self.frame = CGRectMake(0, 0, 334, 250);
UILabel *aLabel1= [[UILabel alloc]init];
UILabel *aLabel2 = [[UILabel alloc]init];
self.label1 = aLabel1;
self.label2 = aLabel2;
self.label1.text = #"Happy";
self.label2.text = #"coding";
UIImageView *bg1 = [[UIImageView alloc]init];
bg1.tag = 100;
UIImageView *bg2 = [[UIImageView alloc]init];
bg2.tag = 200;
[self addSubview:bg1]; // you must add your background views first
[self addSubview:bg2];
[self addSubview:label1];//then other views
[self addSubview:label2];
[aLabel1 release];
[aLabel2 release];
[bg1 release];
[bg2 release];
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
// Configure the view for the selected state
// hear only you can manage your background views, simply i am adding 2 imageviews by setting different colors
[super setSelected:selected animated:animated];
self.backgroundColor = [UIColor greenColor];
if(selected)
{
self.label1.backgroundColor = [UIColor redColor];
self.label2.backgroundColor = [UIColor brownColor];
UIImageView *bg1 = (UIImageView *)[self viewWithTag:100];
bg1.frame = CGRectMake(0, 0,334/2, 250);
bg1.backgroundColor = [UIColor yellowColor];
}
else
{
self.label1.backgroundColor = [UIColor brownColor];
self.label2.backgroundColor = [UIColor redColor];
UIImageView *bg2 =(UIImageView *) [self viewWithTag:200];
bg2.frame = CGRectMake(35, 0, 334/2, 250);
bg2.backgroundColor = [UIColor lightGrayColor];
}
}
-(void)layoutSubviews
{
//i am setting the frame for each views that i hav added
[super layoutSubviews];
self.label1.frame = CGRectMake(10, 10, 60, 35);
self.label2.frame = CGRectMake(65, 10, 60, 35);
}
hope helps u :)
note: i am using "without ARC"

UIView with rounded corners: I've forgotten something

I'm developing an iOS application with latest SDK.
I have this custom UIView:
#define ANNOTATION_WIDTH 250
#define ANNOTATION_HEIGHT 200
#implementation CustomView
- (id)initwithTitle:(NSString* )title subTitle:(NSString* )subTitle
{
CGRect annotationFrame =
CGRectMake(10, 10, ANNOTATION_WIDTH, ANNOTATION_HEIGHT);
if ([self initWithFrame:annotationFrame])
{
self.backgroundColor = [UIColor redColor];
self.opaque = YES;
/*
UILabel* nameLabel =
[[UILabel alloc] initWithFrame:CGRectMake(0, 0, ANNOTATION_WIDTH, 20.0)];
nameLabel.backgroundColor = [UIColor whiteColor];
nameLabel.textAlignment = NSTextAlignmentCenter;
//nameLabel.text = coordinate.name;
nameLabel.text = title;
[nameLabel sizeToFit];
[nameLabel setFrame: CGRectMake(0,
0,
nameLabel.bounds.size.width + 8.0,
nameLabel.bounds.size.height + 8.0)];
[self addSubview:nameLabel];
UILabel* placeLabel =
[[UILabel alloc] initWithFrame:CGRectMake(25, 0, ANNOTATION_WIDTH, 20.0)];
placeLabel.backgroundColor = [UIColor whiteColor];
placeLabel.textAlignment = NSTextAlignmentCenter;
//placeLabel.text = coordinate.place;
placeLabel.text = subTitle;
[placeLabel sizeToFit];
[placeLabel setFrame:CGRectMake(25,
0,
placeLabel.bounds.size.width + 8.0,
placeLabel.bounds.size.height + 8.0)];
[self addSubview:placeLabel];
*/
}
return self;
}
I will show a title and a subTitle, but now that code is comment because I'm testing something.
To add this custom view to an UIViewController I do this:
#import "ViewController.h"
#import "CustomView.h"
#import <QuartzCore/QuartzCore.h>
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
CustomView* cView = [[CustomView alloc] initwithTitle:#"Titulo" subTitle:#"Subtitulo"];
cView.layer.cornerRadius = 10;
cView.layer.masksToBounds = YES;
[self.view addSubview:cView];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
If I don't show title and subTitle and I don't see my customView, but I show title and subTitle I only see rounded upper left corner.
I have tried this also, and it doesn't work:
CustomView* cView = [[CustomView alloc] initwithTitle:#"Titulo" subTitle:#"Subtitulo"];
cView.layer.cornerRadius = 10;
cView.clipsToBounds = YES;
Is there any way to show a UIView with rounded corners without adding any subview?
I don't know what it is happening and Id on't know why I get rounded upper left corner only.
Try this:
cView.layer.cornerRadius = 10.0f;
cView.layer.masksToBounds = YES;
cView.layer.opaque = NO;
[self.view addSubview:cView];
are you tried this
[self.layer setCornerRadius:10];
[self.layer setMasksToBounds:YES];

Resources