Round left border of a UIButton - ios

To round the bottom left corner of a UIButton, I took code from this answer and modified the line: borderLayer.strokeColor = GenerateShape.UIColorFromHex(0x989898, alpha: (1.0-0.3)).CGColor b/c it didn't work.
However, the left border of the UIButton is not rounded. How to fix?
Code
button.frame = CGRect(x: 0, y: 0, width: 0.5*popUpView.frame.width, height: 0.25*popUpView.frame.height)
button.layer.borderWidth = 3
button.roundBtnCorners(roundedCorners, radius: cornerRadius)
extension UIButton{
// Round specified corners of button
func roundBtnCorners(_ corners:UIRectCorner, radius: CGFloat)
{
let borderLayer = CAShapeLayer()
borderLayer.frame = self.layer.bounds
borderLayer.strokeColor = UIColor(red: 168/266, green: 20/255, blue: 20/255, alpha: 0.7).cgColor
borderLayer.fillColor = UIColor.clear.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);
}
}

Istead of:
self.layer.addSublayer(borderLayer)
Try:
self.layer.mask = borderLayer

I cannot see how you are creating the parameters for roundBtnCorners but below is the line I changed in your code and it worked. I would check to make sure you are passing the correct parameters.
button.roundBtnCorners(.bottomLeft , radius: 10)

Solved it! It was because my button.layer.borderWidth = 3 was drawing a really thick rectangle, so I couldn't see the border drawn by roundBtnCorners
I deleted the line below:
button.layer.borderWidth = 3
Result:

Related

How to apply corner radius to certain corners and add shadow

Is there a way to apply rounded corners to certain corners only, and at the same time apply a shadow layer?
I tried doing that using the following extension, but that didn't work for me:
extension UIView {
func roundCorners(_ corners: UIRectCorner, radius: CGFloat, shadow: Bool = false) {
let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()
mask.path = path.cgPath
self.layer.mask = mask
if shadow {
self.layer.shadowColor = UIColor.black.cgColor
self.layer.shadowOffset = CGSize(width: 0, height: 2)
self.layer.shadowOpacity = 0.3
self.layer.shadowRadius = 3.0
}
}
}
So, I tossed in some code into playground and had a quick playground, based on the example from How to round only specific corners using maskedCorners
let view = UIView(frame: CGRect(x: 100, y: 100, width: 500, height: 500))
view.backgroundColor = UIColor.white
view.layer.cornerRadius = 15
view.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMaxYCorner]
view.layer.shadowColor = UIColor.black.cgColor
view.layer.shadowOffset = CGSize(width: 0, height: 0)
view.layer.shadowOpacity = 1.0
view.layer.shadowRadius = 4
//view.layer.shadowPath = UIBezierPath(rect: view.bounds).cgPath
view.layer.shouldRasterize = false
let outter = UIView(frame: CGRect(x: 0, y: 0, width: 700, height: 700))
outter.backgroundColor = UIColor.red
outter.addSubview(view)
outter
I did some testing:
With no corner radius
With masked corner radius
With reduced shawdowRadius
And just to be sure, increased corner radius

Shadow not being applied if setting corner radius

I am trying to add corner radius to bottmLeft and bottomRight corner and also to add shadow to it. But for some reason if I add those corner radiuses the shadow disappears. What causes this?
This is what I do:
I Have extension:
extension UIView {
func roundCorners(_ corners: UIRectCorner, radius: CGFloat) {
self.layoutIfNeeded()
let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()
mask.path = path.cgPath
self.layer.mask = mask
}
}
Apply corners:
myView.roundCorners([.bottomLeft, .bottomRight], radius: 35)
Add shadow extension:
func addShadow(offset: CGSize, color: UIColor, radius: CGFloat, opacity: Float) {
let layer = self.layer
layer.masksToBounds = false
layer.shadowOffset = offset
layer.shadowColor = color.cgColor
layer.shadowRadius = radius
layer.shadowOpacity = opacity
layer.shadowPath = UIBezierPath.init(roundedRect: layer.bounds, cornerRadius: layer.cornerRadius).cgPath
let backgroundCGColor = self.backgroundColor?.cgColor
self.backgroundColor = nil
layer.backgroundColor = backgroundCGColor
}
And add shadow:
myView.addShadow(offset: CGSize.init(width: 0.0, height: 10.0) , color: UIColor.blue, radius: 35.0, opacity: 1.0)
Why the shadow disappears after adding the rounded corners?
myView.layer.shadowPath needs to be initialized with a UIBezierPath. Just give it the same frame and bounds as myView.

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

set my gradient to an arc of BezierPath [duplicate]

This question already has answers here:
How to draw a circle path with color gradient stroke
(4 answers)
Closed 5 years ago.
I've read some topics about but can't apply to me... I try to apply a gradient color to an arc drawed with a UIBezierPath.
The problem is that my gradient fill all the circle and not just the ring.
func layerWith(size: CGSize, color: UIColor) -> CALayer {
let layer: CAShapeLayer = CAShapeLayer()
var path: UIBezierPath = UIBezierPath()
let lineWidth: CGFloat = 2
layer.backgroundColor = nil
layer.path = path.cgPath
layer.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height)
switch self {
case .ring:
path.addArc(withCenter: CGPoint(x: size.width / 2, y: size.height / 2),
radius: size.width / 2,
startAngle: 0,
endAngle: CGFloat(2 * M_PI),
clockwise: false);
layer.fillColor = UIColor.clear.cgColor
layer.strokeColor = color.cgColor
layer.lineWidth = lineWidth
let colorGradStart = UIColor(red: 0/255, green: 209/255, blue: 192/255, alpha: 1.0)
let colorGradEnd = UIColor(red: 00/255, green: 99/255, blue: 91/255, alpha: 1.0)
let gradient = CAGradientLayer()
gradient.frame = path.bounds
gradient.colors = [colorGradStart.cgColor, colorGradEnd.cgColor]
let shapeMask = CAShapeLayer()
shapeMask.path = path.cgPath
gradient.mask = shapeMask
layer.addSublayer(gradient)
}
return layer
}
So this code, apply the gradient to all the filled form, me i just need the arc.
One way to do it is to apply your CAShapeLayer to your gradient layer as a mask. Then it reveals the gradient.
You should set shapeMask's fillColor and strokeColor, not the layer.

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.

Resources