UILabel Background Color Leaks to Border - ios

I'm creating a UILabel to which I set the background color and corner radius with the following code:
self.scoreLabel.backgroundColor = [UIColor DISRed];// custom red`
self.scoreLabel.layer.masksToBounds = YES;
self.scoreLabel.layer.cornerRadius = self.scoreLabel.frame.size.width/2;
self.scoreLabel.layer.borderWidth = 8.0;
self.scoreLabel.layer.borderColor = [[UIColor DISNavy] CGColor];
However the background's color seems to be leaking to the edge of the border (see image). Any ideas why? Any idea on how to fix it?

I was also facing the same problem. It was a silly mistake. I always forget to tick clipToBounds in case of cornerRadius.
So, just ticking the Clip to Bounds for UILabel in Storyboard fixed my problem.
And yes, we need to keep the below code too:
label.layer.masksToBounds = true

I ran into the same problem with the UIButton's background color leaking around the edge of its border.
Instead of setting the UIButton background color on the UIButton, set it on the UIButton's layer.
Replace:
self.scoreLabel.backgroundColor = [UIColor DISRed];// custom red`
With this:
self.scoreLabel.layer.backgroundColor = [[UIColor DISRed] CGColor];// custom red`

I created my own UILabel and background colour does not seem to be leaking.
Write this in .h file of your project.
UILabel *label;
Write this in .m file of your project.
label=[[UILabel alloc]initWithFrame:CGRectMake(100, 300, 100, 100)];//Set frame of label in your viewcontroller.
[label setBackgroundColor:[UIColor redColor]];//Set background color of label.
[label setText:#"Label"];//Set text in label.
[label setTextColor:[UIColor blackColor]];//Set text color in label.
[label setTextAlignment:NSTextAlignmentCenter];//Set text alignment in label.
[label.layer setCornerRadius:50.0];//Set corner radius of label to change the shape.
[label.layer setBorderWidth:8.0f];//Set border width of label.
[label setClipsToBounds:YES];//Set its to YES for Corner radius to work.
[label.layer setBorderColor:[UIColor greenColor].CGColor];//Set Border color.
[self.view addSubview:label];//Add it to the view of your choice.

It is probably anti aliasing issue. you can better fix it by adding a bezier path around the corners.
CAShapeLayer *subLayer = [[CAShapeLayer alloc] init];
[subLayer setFillColor:[UIColor clearColor].CGColor];
[subLayer setStrokeColor:[UIColor whiteColor].CGColor];
[subLayer setLineWidth:1.0];
[subLayer setPath:[UIBezierPath bezierPathWithRoundedRect:imageView.bounds cornerRadius:imageView.layer.cornerRadius].CGPath];
[imageView.layer addSublayer:subLayer];

For those who are still facing the issue of border color leaking out:
Go through the below code, please note you will need to set frames & border width as per your requirement, I'm setting the position as view's center
let badgeSize: CGFloat = 10
let redBadge = UIView(frame: CGRect(x: view.center.x, y:view.center.y, width: badgeSize, height: badgeSize))
redBadge.layer.borderColor = UIColor.white.cgColor
redBadge.layer.borderWidth = 2
redBadge.backgroundColor = .red
redBadge.layer.cornerRadius = badgeSize * 0.5
redBadge.clipsToBounds = true
redBadge.layer.masksToBounds = true
redBadge.maskLayerOnView(radius: badgeSize * 0.5)
view.addSubview(redBadge)
Secondly, we need to write an extension on UIView
extension UIView{
func maskLayerOnView(radius: CGFloat){
let maskLayer = CAShapeLayer()
maskLayer.path = UIBezierPath(roundedRect: self.bounds,
byRoundingCorners: [.allCorners],
cornerRadii: CGSize(width: radius,
height: radius)).cgPath
self.layer.mask = maskLayer
}
}
This code snippet removes the border color separating out, one can replicate this behaviour on any kind of views.
For detailed explanation please see this article.

Well, a lot of answers...
I found the problem persists, as long as the UIViews background color is used and not the background color of the UIViews 'layer'. In addition, of course, masking needs to be enabled.
For a UICollectionViewCell subclass the code is:
- (void)prepare
{
self.contentView.layer.backgroundColor = UIColor.redColor.CGColor;
self.contentView.layer.cornerRadius = 25.0;
self.contentView.layer.borderColor = UIColor.blackColor.CGColor;
self.contentView.layer.borderWidth = 1.0;
//Enable to optimize image views: self.contentView.layer.shouldRasterize = YES;
//Enable to optimize image views: self.contentView.layer.rasterizationScale = UIScreen.mainScreen.scale;
self.contentView.layer.masksToBounds = YES;
self.contentView.clipsToBounds = YES;
}
To make the setting of the background color more comfortable and less error prone, some could add this:
/*
setBackgroundColor:
*/
- (void)setBackgroundColor:(UIColor *)p_BackgroundColor
{
super.backgroundColor = nil;
self.contentView.layer.backgroundColor = p_BackgroundColor.CGColor;
self.contentView.layer.masksToBounds = YES;
self.contentView.clipsToBounds = YES;
}

Related

iOS Button with round corners and a shadow

I have searched and tried the various solutions but without success. What I would like is a button background with rounded corners and a shadow. I can make one or the other happen but not both at the same time. Any help would be very welcome.
viewDepositButton_.layer.cornerRadius = 5.0;
CAGradientLayer *viewLayer = [CAGradientLayer layer];
[viewLayer setColors:aloColors];
[viewLayer setFrame:viewDepositButton_.bounds];
[viewDepositButton_.layer insertSublayer:viewLayer atIndex:0];
viewDepositButton_.clipsToBounds = YES;
viewDepositButton_.layer.shadowColor = [UIColor colorWithRed:0.46 green:0.46 blue:0.46 alpha:1.0].CGColor;
viewDepositButton_.layer.shadowOpacity = 0.8;
viewDepositButton_.layer.shadowRadius = 8;
viewDepositButton_.layer.shadowOffset = CGSizeMake(8.0f, 8.0f);
viewDepositButton_.clipsToBounds = YES; or viewDepositButton_.layer.masksToBounds = YES; will clip everything outside your layer - including the shadow.
However you have few options:
Put your button under a parent view, which will have the same corner radius and the shadow you want, but will have clipsToBounds = NO. This way you'll have your button as a subview of a view which has the shadow.
Use an image for your button, which has the rounded corners and set your buttons clipsToBounds to NO
Hope this helps
I was able to get your code to work by the following and it looks fine. Make sure you call your methods in proper sequence.
viewDepositButton_.layer.cornerRadius = 5.0;
viewDepositButton_.layer.borderWidth = 1.0;
viewDepositButton_.layer.shadowColor = [UIColor colorWithRed:0.46 green:0.46 blue:0.46 alpha:1.0].CGColor;
viewDepositButton_.layer.shadowRadius = 8;
viewDepositButton_.layer.shadowOpacity = 0.8;
viewDepositButton_.layer.shadowOffset = CGSizeMake(8.0f, 8.0f);
CAGradientLayer *viewLayer = [CAGradientLayer layer];
[viewLayer setColors:aloColors];
[viewLayer setFrame:viewDepositButton_.bounds];
[viewDepositButton_.layer insertSublayer:viewLayer atIndex:0];
[viewDepositButton_ viewLayer];}
Here is my code for setting up a rounded corner button with shadow.
button.layer.cornerRadius = 15;
button.layer.shadowRadius = 2.0f;
button.layer.shadowColor = [UIColor lightGrayColor].CGColor;
button.layer.shadowOffset = CGSizeMake(-1.0f, 3.0f);
button.layer.shadowOpacity = 0.8f;
button.layer.masksToBounds = NO;
Overall, the code is pretty straightforward. Please comment if you have any question, concerns or bugs.

IOS: UIImageView set border white radius and shadow

Here is my code for set the border, shadow and corner
// set border
[self.avatarImageView.layer setBorderColor: [[UIColor whiteColor] CGColor]];
[self.avatarImageView.layer setBorderWidth: 2.0];
// set shadow
[self.avatarImageView.layer setShadowOffset:CGSizeZero];
[self.avatarImageView.layer setShadowOpacity:1.0];
self.avatarImageView.clipsToBounds = NO;
// set corner
self.avatarImageView.layer.cornerRadius = 10.0;
self.avatarImageView.layer.masksToBounds = YES;
If I only use the code for set border and set corner, it work well like this
But if I add the code set corner, I will got the result like this (the border and corner radius work, but the shadow is gone)
However the code for set corner work perfect if it stay alone.
Please guide me what to do. Any help would be appreciate
Update
Follow #ozgur answer. Add 2 lines to my code, it will give a very beautiful view but the shadow is a little bit smaller
self.avatarImageView.layer.shouldRasterize = YES;
self.avatarImageView.layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:self.avatarImageView.bounds cornerRadius:10].CGPath;
Rounded corners requires masksToBounds to be set to YES. Because of that nothing past the boundaries (like a shadow) can be shown, because it will be masked/clipped off. If you disable masksToBounds so that it will show then the rounded corners wont work because they are unable to mask/clip your image into the rounded shape because you disabled masksToBounds.
Therefor, you can't do both at the same time on one view—so you need TWO views.
You need to make a UIView the same dimensions as your UIImageView and make the UIImageView a subview of your UIView.
Then on your UIImageView set masksToBounds to YES, and on its' superview (the UIView with the same dimensions) set masksToBounds to NO and add the properties accordingly.
Change your code to this: (typed it all w/o using xCode so it's possible I have typos)
UIView *avatarImageViewHolder = [[UIView alloc] initWithFrame:self.avatarImageView.frame];
avatarImageViewHolder.backgroundColor = [UIColor clearColor];
[avatarImageView.superview addSubview:avatarImageViewHolder];
avatarImageViewHolder.center = avatarImageView.center;
[avatarImageViewHolder addSubview:avatarImageView];
avatarImageView.center = CGPointMake(avatarImageViewHolder.frame.size.width/2.0f, avatarImageViewHolder.frame.size.height/2.0f);
self.avatarImageView.layer.masksToBounds = YES;
avatarImageViewHolder.layer.masksToBounds = NO;
// set avatar image corner
self.avatarImageView.layer.cornerRadius = 10.0;
// set avatar image border
[self.avatarImageView.layer setBorderColor: [[UIColor whiteColor] CGColor]];
[self.avatarImageView.layer setBorderWidth: 2.0];
// set holder shadow
[avatarImageViewHolder.layer setShadowOffset:CGSizeZero];
[avatarImageViewHolder.layer setShadowOpacity:1.0];
avatarImageViewHolder.clipsToBounds = NO;
You need to add a container view and move your imageview inside that container view, Use this code after doing so:
CALayer *imageViewLayer= self.imageView.layer;
imageViewLayer.cornerRadius= 20.0f;
imageViewLayer.masksToBounds= YES;
CALayer *containerLayer = self.containerView.layer;
containerLayer.borderColor= [UIColor whiteColor].CGColor;
containerLayer.borderWidth= 3.0f;
containerLayer.cornerRadius= 20.0f;
containerLayer.shadowOffset = CGSizeMake(0, 0);
containerLayer.shadowColor = [UIColor blackColor].CGColor;
containerLayer.shadowRadius = 10.0f;
containerLayer.shadowOpacity = 0.80f;
containerLayer.masksToBounds= NO;
containerLayer.shadowPath = [[UIBezierPath bezierPathWithRect:containerLayer.bounds] CGPath];
Feel free to tweak the settings as per your need. Enjoy!
You should update layer.shadowPath if you don't want the shadow to get clipped:
self.avatarImageView.layer.shouldRasterize = YES;
self.avatarImageView.layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:self.avatarImageView.bounds cornerRadius:10].CGPath;
For this trick to work, clipsToBounds and his brother masksToBounds should be set to NO.
Thus, if you have an image whose size is greater than the avatarView's own bounds, you should define avatarImageView as plain UIView, create another imageView to display the image set its masksToBounds to YES and add it as a subview to avatarImageView so that you'll have a good cornered and shadowed view capable of displaying the clipped image.
You should set self.avatarImageView.clipsToBounds = YES; in set corner

iOS: programmatically draw a rectangle on top of a button

I need to draw a rectangle on top of a UIButton. Assume that there's a UIButton called hideMe, and this button has 100x50 size. I want to place a 100x10 rectangle on top of this button every time a user receives a message. If the user receives five messages, then the button will be completely covered by the rectangles. How do I do this?
CALayer *topBorder = [CALayer layer];
topBorder.borderColor = [UIColor redColor].CGColor;
topBorder.backgroundColor = [UIColor blackColor].CGColor;
topBorder.borderWidth = 2;
topBorder.frame = CGRectMake(0, 15, <tempButton>.frame.size.width, <tempButton>.frame.size.height-30);
[<tempButton>.layer addSublayer:topBorder];
The above code helps you to draw the rectangle.You can increase the layer frames to cover full.
try this
#import <QuartzCore/QuartzCore.h>
here we are drawing our own border rect and sub viewing it to our button
-(UIView*)borderRectWithYvalue:(CGFloat)yValue
{
UIView * rect = [[UIView alloc] initWithFrame:CGRectMake(0,yValue, 100, 10)];
rect.backgroundColor = [UIColor lightGrayColor];
rect.layer.borderColor = (__bridge CGColorRef)([UIColor redColor]);
rect.layer.borderWidth = 2.0f;
return rect;
}
and call this method when and where you want to add border to your button with your custom y value
for ex
[yourButton addSubview:[self borderRectWithYvalue:10.0]];

CALayer inner border corner radius

I have a UITextView where I set the border width, border color, and corner radius properties on its layer, and the outside looks great. However, the inner part of the border doesn't have rounded corners like the outer part, and it looks kind of funny. Is there a way to round the inner corners of the border?
Edit:
Here's the code I used in the initWithFrame: method:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = UIColorFromRGB(0xdedede);
self.layer.cornerRadius = kTextFieldCornerRadius;
self.layer.borderColor = UIColorFromRGB(0xD4974C).CGColor;
self.layer.borderWidth = 3.0f;
self.font = [UIFont fontWithName:#"HelveticaNeue-Bold" size:12.0f];
[self setClipsToBounds:YES];
[self.layer setMasksToBounds:YES];
}
return self;
}
And here's a screenshot of what it looks like now:
Notice the outer corners are rounded as expected, but the inner corners of the border are pointed rather than rounded. That's what I'm trying to fix. Thanks for your help!
Try to set this,
[txtView setClipsToBounds:YES]; //Confirms subviews are confined to the bounds of the view
[txtView.layer setMasksToBounds:YES]; //Confirms sublayers are clipped to the layer’s bounds
EDIT
Probably the value of kTextFieldCornerRadius is set to low in your case.
If I set kTextFieldCornerRadius = 7; see I can get perfect output.
try to increase your radius value.
Import QuartzCore framework and add the following lines of code :
OBJECTIVE - C
UIView *yourView=[[UIView alloc]initWithFrame:CGRectMake(0, 50, 320, 430)];
yourView.layer.borderColor = [UIColor redColor].CGColor;
yourView.layer.borderWidth = 10.0f;
yourView.layer.cornerRadius = 20.0f;
[yourView setClipsToBounds:YES];
[yourView.layer setMasksToBounds:YES];
SWIFT - 3.0.1 (playground code)
//: Playground - noun: a place where people can play
import UIKit
import PlaygroundSupport
import QuartzCore
let containerView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 375.0, height: 100.0))
containerView.backgroundColor = UIColor.white
containerView.layer.borderWidth = 10
containerView.layer.borderColor = UIColor.red.cgColor
containerView.clipsToBounds = true
containerView.layer.masksToBounds = true
containerView.layer.cornerRadius = 20
PlaygroundPage.current.liveView = containerView
PlaygroundPage.current.needsIndefiniteExecution = true
OUTPUT :
IMPORTANT:
Make sure the cornerRadius is greater than the borderWidth . Else you will not be able to see the difference.

iOS6 Add Shadow to A Container UIView With A Corner Radius

How can an encompassing UIView have both a shadow and a corner radius at the same time?
I have tried other solutions suggested on SO multiple times, but unfortunately they do not seem to work for iOS6 (or at least not for me)
So I thought I might post this, so that an iOS6 solution can be found.
I have a container UIView which contains two subviews
- a custom UIImageView
- a custom UIView
I would like the entire UIView to have a corner radius of 2.5, but I would also like the UIView to have a shadow. However, so far, I get only 1 of these 2 desires, never both at the same time.
Here is my code, I have different versions of it with my different attempts with SO solutions, but this is just one of my versions.
self.layer.shouldRasterize = YES;
self.layer.rasterizationScale = [UIScreen mainScreen].scale;
self.layer.cornerRadius = 2.5;
self.layer.masksToBounds = YES;
self.layer.shadowColor = [UIColor colorWithWhite:0.0 alpha:0.1].CGColor; //0.1
self.layer.shadowPath = [UIBezierPath bezierPathWithRect:self.bounds].CGPath;
self.layer.shadowOpacity = 1.0;
self.layer.shadowRadius = 3.0;
^here self is the containing custom UIView with two subviews described above
Does anyone know of an iOS6 solution to this problem?
UPDATE
So, I do not need a border colour, so I was not adding that when I saw the solutions, but this time I added that, using the solution in the comment below, and it seems that the UIView is getting rounded, but I really want the combined UIImageView and UIView to get rounded.
So basically, the UIImageView is on top, and the UIView is on the bottom.
So how do I get only the top of the UIImageView to be rounded, and only the bottom of the UIView to be rounded.
Thanks.
Note: shadows work as one whole object, but the corner radius is not working as one whole object?
I figured it out.
self.layer.shouldRasterize = YES;
self.layer.rasterizationScale = [UIScreen mainScreen].scale;
self.layer.shadowColor = [UIColor colorWithWhite:0.0 alpha:0.8].CGColor;
self.layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:self.layer.bounds cornerRadius:self.layer.cornerRadius].CGPath;
self.layer.shadowOpacity = 1.0;
self.layer.shadowRadius = 3.0;
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
[self addSubview:container];
[container addSubview:self.someCustomUIView];
[container addSubview:self.someCustomImageView];
container.layer.cornerRadius = 2.5;
container.layer.masksToBounds = YES;
So basically:
I set the shadow of the main UIView.
I created a container subview which contains two other subviews
I set the corner radius of the container subview
Voila! It works!
I hope this works for other people who have multiple subviews in one UIView
I'd like to thank everyone for their help. :)
I think you should change this line of code:
self.layer.masksToBounds = YES;
to this one
self.layer.masksToBounds = NO;
If you set masksToBounds to YES, then you won't see anything that extends beyond the view's bounds, and this is the case with a shadow.
This code is from my current project (iOS 6) and it works fine. I can see both rounded corners and a shadow.
self.layer.masksToBounds = NO;
self.layer.cornerRadius = 5.0;
self.layer.shadowColor = [UIColor blackColor].CGColor;
self.layer.shadowOffset = CGSizeMake(0, -1);
self.layer.shadowOpacity = 0.6;
UIBezierPath *shadowPath = [UIBezierPath bezierPathWithRect: self.layer.bounds];
self.layer.shadowPath = shadowPath.CGPath;

Resources