CALayer inner border corner radius - ios

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.

Related

How to draw a 1px line in storyBoard?

As we know, the table view separator is so thin and beautiful. Sometimes we have to build some separator line in storyboard or nib, the min number is 1, but actually the line appears much thicker than we expected.
My question is how to draw a 1px line in storyboard?
Xcode 9 Swift: You can add a thin seperator with 1px line in the Storyboard using UIView.
Under Size Inspector, Just set the height to 1, width example to 360.
Apple documentation on UIView.
I got your point too, finally I find way out.
As we know, if we draw a line and set the height by code, we can set the height equal to (1.0 / [UIScreen mainScreen].scale).
But here, you wanna to draw in storyboard.
My way is subclass UIView or UIImageView, based on your demand as OnePXLine. In OnePXLine class, override layoutSubviews like below:
- (void)layoutSubviews {
[super layoutSubviews];
CGRect rect = self.frame;
rect.size.height = (1 / [UIScreen mainScreen].scale);
self.frame = rect;
}
And you can draw 1 px line in storyboard by use this class.
Goodluck!
This would help you if you're coding in Swift:
func lineDraw(viewLi:UIView)
{
let border = CALayer()
let width = CGFloat(1.0)
border.borderColor = UIColor(red: 197/255, green: 197/255, blue: 197/255, alpha: 1.0).CGColor
border.frame = CGRect(x: 0, y: viewLi.frame.size.height - width, width: viewLi.frame.size.width, height: viewLi.frame.size.height)
border.borderWidth = width
viewLi.layer.addSublayer(border)
viewLi.layer.masksToBounds = true
}
You can do like in any UIControl/UIElement for this and change the height as 1
If you want to 1 Point use this - 1
If you want to 1pixel Use this - 1.0 / UIScreen.mainScreen().scale
Objective-C
UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0, 50, self.view.frame.size.width, 1)]; // customize the frame what u need
[lineView setBackgroundColor:[UIColor yellowColor]]; //customize the color
[self.view addSubview:lineView];
Swift
var lineView = UIView(frame: CGRect(x: 0, y: 50, width: self.view.frame.size.width, height: 1))
lineView.backgroundColor = UIColor.yellow
self.view.addSubview(lineView)
If you want a more information see this once
you can assign float value for view frame . so what you can do is take any view (lable,textview,view,textfield) and assign height as 0.4f or something programatically and width to match self width.
lable.frame = CGRectMake(0,0,width of self.view,0.4f);
Try it in cellForRowAtIndex
UIView* separatorLineView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, 1)];
separatorLineView.backgroundColor = [UIColor colorWithRed:242/255.0f green:222/255.0f blue:52/255.0f alpha:1.0];
[cell.contentView addSubview:separatorLineView];
Swift 5 code base on what #childrenOurFuture answered:
class OnePXLine: UIView {
override func layoutSubviews() {
super.layoutSubviews()
var rect = self.frame;
rect.size.height = (1 / UIScreen.main.scale);
self.frame = rect;
}
}

draw a circle of rectangles in Xcode

I have tried this code to draw a circle of rectangle
incNumberDefault=0;
for (int i = 0; i < maxNumber; i++) {
incNumberDefault = incNumberDefault +5;
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(incNumberDefault, 100, 3, 15)];
myView.center = CGPointMake(130,130);
myView.transform = CGAffineTransformMakeRotation(DegreesToRadians(incNumberDefault));
myView.backgroundColor = [UIColor lightGrayColor];
[self.speedDisplay addSubview:myView];
}
the outputs seems close circle where as i need transparent or space in middle of circle.
You can set UIView cornerRadius to half of the UIView width or height like,
myView.layer.cornerRadius=myview.frame.size.width / 2; or
myView.layer.cornerRadius=myview.frame.size.height / 2
For that you have to give same width and height to your UIView.
Try this :
// initialize the view with same height and width for perfect circle.
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 15, 15)];
// round the corner of view with required radius.
myView.layer.cornerRadius = myView.frame.size.width/2; // height can also be used
// circle with space in middle.
myView.backgroundColor = [UIColor clearColor];
myView.layer.borderColor = [UIColor lightGrayColor].CGColor;
myView.layer.borderWidth = 2.0f;
[self.speedDisplay addSubview:myView];
Hope it will solve your problem.
Thank you for your answer but i want to develop a dashed circle in certain distance and i have tired this code :
incNumberDefault=0;
for (int i = 0; i < maxNumber; i++) {
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(100+60 * sin(incNumberDefault), 100+60*cos(incNumberDefault), 3, 15)];
//myView.transform = CGAffineTransformMakeRotation(DegreesToRadians(incNumberDefault));
myView.backgroundColor = [UIColor lightGrayColor];
[self.speedDisplay addSubview:myView];
incNumberDefault = incNumberDefault +9;
}
but it generate random rectangle in a circle.
I want it in sequence.
Thank you.

UILabel Background Color Leaks to Border

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

Drop a shadow to right and bottom of uiview

I have to drop a shadow to the right and bottom of uiview.Im doing this in interface builder.But I see the shadow dropped to top of it.Tried differnt sizes.but couldn't get it.
layer.masksToBound=No
layer.shadowOpacity=0.15
layer.shadowRadius=2
layer.shadowOffSet={10,-10} //Values being set in Interfacebuilder.
Still this drops shadow at top.What should I do to get at bottom of view.
Try the following code, it might help you
myView.layer.shadowColor = [UIColor purpleColor].CGColor;
myView.layer.shadowOffset = CGSizeMake(5, 5);
myView.layer.shadowOpacity = 1;
myView.layer.shadowRadius = 1.0;
myView.layer.maskToBounds = NO;
I tested this code and it's working and output is:
Hi I have used below code ,it will provide you with shadow you want.
UIBezierPath *shadowPath = [UIBezierPath bezierPathWithRect:_viewShadow.bounds];
_viewShadow.layer.masksToBounds = NO;
_viewShadow.layer.shadowColor = [UIColor blackColor].CGColor;
_viewShadow.layer.shadowOffset = CGSizeMake(10.0f, 5.0f); /*Change value of X n Y as per your need of shadow to appear to like right bottom or left bottom or so on*/
_viewShadow.layer.shadowOpacity = 0.5f;
_viewShadow.layer.shadowPath = shadowPath.CGPath;
Also masksToBounds is imp as it disables the clipping of sublayers that extend further than the view's bounds. If you put it YES then you won't see shadow as it clips sublayer where else in NO it allow to extent layer.
In Swift 3, CGSizeMake no longer exists. It has been changed to CGSize(width: 20, height: 10). So the shadowOffset can be set like this in Swift 3:
myView.layer.shadowOffset = CGSize(width: 20, height: 10)
I found out that these values give a nice result :
myView.layer.shadowColor = UIColor.black.cgColor
myView.layer.shadowOpacity = 0.25
myView.layer.shadowRadius = 3
myView.layer.shadowOffset = CGSize(width: 1, height: 1) // shadow on the bottom right
I think your shadow offset is incorrect. It should be { 10 , 10} like:
[layer setShadowOffset:CGSizeMake( 10 , 10 ) ];

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