Issue with rounded corners of ImageView with gradient colour - ios

I created a rectangle using following code and now I need to rounded the corners of this rectangle. I set layer.cornerRadius also, can anyone help me?
My code as below,
private func setGradientBorder(_ ivUser:UIImageView) {
ivUser.layer.masksToBounds = true
ivUser.layer.cornerRadius = ivUser.frame.width / 2
let gradient = CAGradientLayer()
gradient.frame = CGRect(origin: CGPoint.zero, size: ivUser.frame.size)
gradient.colors = [UIColor.blue.cgColor, UIColor.green.cgColor]
let maskPath = UIBezierPath(roundedRect: ivUser.bounds,
byRoundingCorners: [.allCorners],
cornerRadii: CGSize(width: ivUser.frame.width/2, height: ivUser.frame.height/2)).cgPath
let shape = CAShapeLayer()
shape.lineWidth = 2
shape.path = maskPath
shape.strokeColor = UIColor.black.cgColor
shape.fillColor = UIColor.clear.cgColor
gradient.mask = shape
ivUser.layer.addSublayer(gradient)
}
output: gradient does not display properly rounded

This is how UIBezierPath works. Half of the line width will go on one side of the actual path, and half will go on another. Thats why it looks kinda cut out.
You will need to inset your paths rect by half of the line width, something like this:
let lineWidth: CGFloat = 2
let maskPath = UIBezierPath(roundedRect: ivUser.bounds.insetBy(dx: lineWidth/2, dy: lineWidth/2),
byRoundingCorners: [.allCorners],
cornerRadii: CGSize(width: ivUser.frame.width/2, height: ivUser.frame.height/2)).cgPath

Related

UIView with shadow and masked layer

So I have an UIView (called myView) with some mask applied to it.
let maskPath = UIBezierPath(roundedRect: myView.bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: 12, height: 12))
let maskLayer = CAShapeLayer()
maskLayer.frame = myView.bounds
maskLayer.path = maskPath.cgPath
myView.layer.mask = maskLayer
Which layout this way:
What I am failing to do is add some shadow to myView. Since the view's layer have a mask, I am not able to add differents layers to it with shadow.
Does anyone ever had this problem?
set your image color to clear and to the following:
let maskPath = UIBezierPath(roundedRect: redView.bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: 12, height: 12))
let maskLayer = CAShapeLayer()[![enter image description here][1]][1]
maskLayer.fillColor = UIColor.red.cgColor // your color
maskLayer.frame = redView.bounds
maskLayer.path = maskPath.cgPath
redView.layer.addSublayer(maskLayer)
redView.layer.shadowOffset = CGSize(width: 10, height: 10)
redView.layer.shadowColor = UIColor.green.cgColor
redView.layer.shadowOpacity = 1

Add a shadow with CAShapeLayer?

I have a CAShapeLayer with bottom rounded corners only. What I want is to add a shadow at the bottom, but it's not working, even though the code looks obviously right. All it does it round the bottom corners but I don't see a shadow.
let shapeLayer = CAShapeLayer()
let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: [.bottomLeft, .bottomRight], cornerRadii: CGSize(width: 20, height: 20)).cgPath
shapeLayer.path = path
shapeLayer.shadowColor = UIColor(r: 233, g: 233, b: 233).cgColor
shapeLayer.shadowOffset = CGSize(width: 0.0, height: 2.8)
shapeLayer.shadowOpacity = 1.0
shapeLayer.shadowRadius = 0.0
shapeLayer.shouldRasterize = true
shapeLayer.rasterizationScale = UIScreen.main.scale
layer.rasterizationScale = UIScreen.main.scale
layer.mask = shapeLayer
The shapeLayer is rounding the corners of your view because it's set as the layer's mask. You probably want to add it as a sublayer instead.
Old:
layer.mask = shapeLayer
New:
layer.addSublayer(shapeLayer)
I wrote another answer about adding a shadow to a view with rounded corners here if it helps: https://stackoverflow.com/a/41475658/6658553
Another solution,
The following UIView extension will work with any shape you mask the view with
extension UIView {
func addShadow() {
self.backgroundColor = UIColor.clear
let roundedShapeLayer = CAShapeLayer()
let roundedMaskPath = UIBezierPath(roundedRect: self.bounds,
byRoundingCorners: [.topLeft, .bottomLeft, .bottomRight],
cornerRadii: CGSize(width: 8, height: 8))
roundedShapeLayer.frame = self.bounds
roundedShapeLayer.fillColor = UIColor.white.cgColor
roundedShapeLayer.path = roundedMaskPath.cgPath
self.layer.insertSublayer(roundedShapeLayer, at: 0)
self.layer.shadowOpacity = 0.4
self.layer.shadowOffset = CGSize(width: -0.1, height: 4)
self.layer.shadowRadius = 3
self.layer.shadowColor = UIColor.lightGray.cgColor
}
}

How to get rounded corners only for topLeft and bottomLeft corners?

I've followed other stackoverflow threads and created CAShapeLayer and added it to button layer.
let bazierPath = UIBezierPath.init(roundedRect: button.bounds, byRoundingCorners: [UIRectCorner.bottomLeft, UIRectCorner.topLeft], cornerRadii: CGSize(width: 10.0, height: 10.0 ))
let shapeLayer = CAShapeLayer()
shapeLayer.frame = button.bounds
shapeLayer.path = bazierPath.cgPath
shapeLayer.strokeColor = UIColor.green.cgColor
shapeLayer.lineWidth = 1.0
button.layer.mask = shapeLayer
but the problem is I'm getting corners with clear color but i want them to be green. check for buttons with "Mon" and "Fri" in following image for clear understanding about problem.
in your code you forgot to add the addSublayer to main layer contentView.layer.addSublayer(subLayer) for sample purpose
let contentView = UIView(frame: CGRect(x: CGFloat(50), y: CGFloat(100), width: CGFloat(200), height: CGFloat(100)))
self.view.addSubview(contentView)
let subLayer = CAShapeLayer()
subLayer.fillColor = UIColor.blue.cgColor
subLayer.strokeColor = UIColor.green.cgColor
subLayer.lineWidth = 1.0
subLayer.path = UIBezierPath(roundedRect: contentView.bounds, byRoundingCorners: [UIRectCorner.bottomLeft, UIRectCorner.topLeft], cornerRadii: CGSize(width: 10.0, height: 10.0 )).cgPath
contentView.layer.addSublayer(subLayer)
output
Try to use the following function:
fun createRoundCorners(corners:UIRectCorner, radius: CGFloat)
{
let borderLayer = CAShapeLayer()
borderLayer.frame = self.layer.bounds
borderLayer.strokeColor = // Add your color
borderLayer.fillColor = UIColor.clearColor().CGColor
borderLayer.lineWidth = 1.0
let path = UIBezierPath(roundedRect: self.bounds,
byRoundingCorners: corners,
cornerRadii: CGSize(width: radius, height: radius))
borderLayer.path = path.CGPath
self.layer.addSublayer(borderLayer);
}

UIView with shadow, rounded only top corners and masked bottom edge

I'm struggling to achieve the view that would have rounded only top corners and shadow around it. The whole view should be masked at the bottom by the superview to prevent the shadow to overlap following subview (shadow offset should be (0, 0)).
When I use:
// Adding shadow
let contentSubviewLayer = contentSubview.layer
contentSubviewLayer.masksToBounds = false
contentSubviewLayer.shadowOpacity = 0.3
contentSubviewLayer.shadowRadius = 2.5
contentSubviewLayer.shadowOffset = CGSizeMake(0, 0)
contentSubviewLayer.cornerRadius = 5.0
contentSubviewLayer.shadowPath = UIBezierPath(rect: contentSubview.bounds).CGPath
self.layer.masksToBounds = true
I get:
But after adding masking the bottom edge:
// Adding maskView to round only top corners
let maskLayer = CAShapeLayer()
maskLayer.frame = self.contentSubview.bounds
let roundedPath = UIBezierPath(roundedRect: maskLayer.bounds, byRoundingCorners: [UIRectCorner.TopLeft, UIRectCorner.TopRight], cornerRadii: CGSizeMake(CORNER_RADIUS, CORNER_RADIUS))
maskLayer.fillColor = UIColor.whiteColor().CGColor
maskLayer.backgroundColor = UIColor.clearColor().CGColor
maskLayer.path = roundedPath.CGPath
contentSubview.layer.mask = maskLayer
I'm getting:
The desired effect should be the conjunction of the two above and should resemble something like this with shadows around the left, top and right edges:
Please help!
Thank you in advance.
I tend to use an app called PaintCode to generate the Swift code I need for this type of thing. I did something similar recently and it spat this out for me:
let context = UIGraphicsGetCurrentContext()
//// Color Declarations
let chiesi_light_grey = UIColor(red: 0.851, green: 0.851, blue: 0.851, alpha: 1.000)
//// Shadow Declarations
let chiesi_shadow = NSShadow()
chiesi_shadow.shadowColor = chiesi_light_grey.colorWithAlphaComponent(0.8 * CGColorGetAlpha(chiesi_light_grey.CGColor))
chiesi_shadow.shadowOffset = CGSize(width: 0.1, height: 4.1)
chiesi_shadow.shadowBlurRadius = 2
//// Rectangle Drawing
let rectanglePath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: 50, height: 54), byRoundingCorners: [UIRectCorner.BottomLeft, UIRectCorner.BottomRight], cornerRadii: CGSize(width: 8, height: 8))
rectanglePath.closePath()
CGContextSaveGState(context)
CGContextSetShadowWithColor(context, chiesi_shadow.shadowOffset, chiesi_shadow.shadowBlurRadius, (chiesi_shadow.shadowColor as! UIColor).CGColor)
UIColor.whiteColor().setFill()
rectanglePath.fill()
CGContextRestoreGState(context)
chiesi_light_grey.setStroke()
rectanglePath.lineWidth = 2
rectanglePath.stroke()
Maybe it will help you.

Why UIBezierPath's corners are transparent?

I want to make my TopLeft and TopRight corners with corner radius. It works with this code:
let rectShape = CAShapeLayer()
rectShape.bounds = self.name.frame
rectShape.position = self.name.center
rectShape.path = UIBezierPath(roundedRect: self.name.bounds, byRoundingCorners: .TopLeft | .TopRight, cornerRadii: CGSize(width: 20, height: 20)).CGPath
rectShape.backgroundColor = UIColor.blackColor().CGColor
self.name.layer.mask = rectShape
but it makes the corners transparent, like this:
How can I make them visible?
Bcs it's just a mask, your layer still square. There are many ways to do it, for example, you can paint your own layer and add it as sublayer. This properties should help you:
layer.fillColor = LAYER_COLOR.CGColor;
layer.strokeColor = LAYER_BORDER_COLOR.CGColor;
layer.lineWidth = LAYER_BORDER_WIDTH;
layer.opacity = LAYER_OPACITY;

Resources