How to set Corner Radius to UIBezierPath - ios

I have created following image by UIBezierPath using this code
//// Bezier Drawing
let bezierPath = UIBezierPath()
bezierPath.move(to: CGPoint(x: 360, y: 0))
bezierPath.addCurve(to: CGPoint(x: 360, y: 75), controlPoint1: CGPoint(x: 359.53, y: 30.5), controlPoint2: CGPoint(x: 359.91, y: 55.45))
bezierPath.addCurve(to: CGPoint(x: 360, y: 153.78), controlPoint1: CGPoint(x: 360.35, y: 153.21), controlPoint2: CGPoint(x: 360, y: 153.78))
bezierPath.addCurve(to: CGPoint(x: 180, y: 153.78), controlPoint1: CGPoint(x: 360, y: 153.78), controlPoint2: CGPoint(x: 271.2, y: 212.77))
bezierPath.addCurve(to: CGPoint(x: 0, y: 153.78), controlPoint1: CGPoint(x: 88.8, y: 94.8), controlPoint2: CGPoint(x: 0, y: 153.78))
bezierPath.addLine(to: CGPoint(x: 0, y: 0))
bezierPath.addLine(to: CGPoint(x: 360, y: 0))
UIColor.green.setFill()
bezierPath.fill()
now i want to give corner radius to TopLeft and TopRight of this following Image using Slider.
I have Tried Following code but it did not works for me.
var cornerPath = path
cornerPath = UIBezierPath(roundedRect:self.imgTop.bounds,
byRoundingCorners:[.topLeft, .topRight],
cornerRadii: CGSize(width: CGFloat(cornerRadius),
height: CGFloat(cornerRadius)))
path.lineWidth = 1.0
let maskLayer = CAShapeLayer()
maskLayer.path = cornerPath.cgPath
self.imgTop.layer.mask = maskLayer
let maskLayerTop = CAShapeLayer()
maskLayerTop.fillColor = UIColor.white.cgColor
maskLayerTop.backgroundColor = UIColor.clear.cgColor
maskLayerTop.path = pathTop?.cgPath
maskLayerTop.cornerRadius = CGFloat(cornerRadius)
//maskLayerTop.masksToBounds = true
maskLayerTop.shadowRadius = CGFloat(cornerRadius)
maskLayerTop.fillColor = UIColor.green.cgColor
maskLayerTop.shadowColor = UIColor.blue.cgColor
imgTop.layer.mask = maskLayerTop
I had also tried to applying corner radius to Image view but it did not work.i want corner radius like following image.
Please Help!
.
.
NOTE: I had already create one path to create following Image

before your let bezierPath = UIBezierPath() for curve add
var = cornerRadiudSize = CGSize(width: 50.0, height: 50.0) //this is your global variable that you can change based on the slider and then draw
let p = UIBezierPath(roundedRect: rect, byRoundingCorners: .allCorners, cornerRadii: cornerRadiudSize)
p.addClip()
PS: Instead of all corner set the corners you want

IOS 14, swift 5 version
let bezierPath = UIBezierPath(roundedRect: shareContainerView.bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: 4, height: 4))
let maskLayer = CAShapeLayer()
maskLayer.path = bezierPath.cgPath
shareContainerView.layer.mask = maskLayer

Related

How to give oval shape to UIView with shadow

How to make uiview with oval shape at bottom side only with shadow
You need to use UIBezierPath for this. Here is an example (just need to play with the values):
let layer = CAShapeLayer()
layer.fillColor = UIColor.red.cgColor
layer.shadowOffset = CGSize(width: 0, height: 2)
layer.shadowRadius = 5
layer.shadowColor = UIColor.black.cgColor
layer.shadowOpacity = 0.5
layer.shadowRadius = 2
view.layer.addSublayer(layer)
let path = UIBezierPath()
path.move(to: .zero)
path.addLine(to: CGPoint(x: view.frame.maxX, y: 0))
path.addLine(to: CGPoint(x: view.frame.maxX, y: 50))
path.addQuadCurve(to: CGPoint(x: 0, y: 50), controlPoint: CGPoint(x: view.frame.midX, y: 70))
path.close()
layer.path = path.cgPath
and result:

CAShapeLayer animation issue

I have a CAShapeLayer (below) which is used to draw a bubble. Which all works fine, as per designs but when i start resizing it within a tableView with tableView.beginUpdates() and tableView.endUpdates(). I end up having the old layer in black momentarily. which is looks awful. I am really puzzled on how to solve this. It kinda feels that layers are black, and the fill paints over them like a mask.
I have tried several things as to add/removing the layer in different places. etc. but result is always this.
video to describe it
override func draw(_ rect: CGRect) {
self.layer.backgroundColor = UIColor.clear.cgColor
let fillColor: UIColor = self.shapeColor
let shapeLayer = CAShapeLayer()
shapeLayer.contentsScale = UIScreen.main.scale
let path = UIBezierPath()
shapeLayer.fillColor = fillColor.cgColor
let width = self.bounds.size.width
let height = self.bounds.size.height
path.move(to: CGPoint(x: 3.02, y: height * 0.5))
path.move(to: CGPoint(x: 3.02, y: 24.9))
path.addLine(to: CGPoint(x: 3.02, y: 14.62))
path.addLine(to: CGPoint(x: 3.02, y: 14.62))
path.addCurve(to: CGPoint(x: 17.64, y: -0), controlPoint1: CGPoint(x: 3.02, y: 6.55),controlPoint2: CGPoint(x: 9.57, y: -0))
path.addLine(to: CGPoint(x: width - 15.85, y: 0))
path.addLine(to: CGPoint(x: width - 15.85, y: 0))
path.addCurve(to: CGPoint(x: width, y: 14.62), controlPoint1: CGPoint(x: width - 7.77, y: 0), controlPoint2: CGPoint(x: width, y: 6.55))
path.addLine(to: CGPoint(x: width, y: height - 15.1))
path.addLine(to: CGPoint(x: width, y: height - 15.1))
path.addCurve(to: CGPoint(x: width - 15.85, y: height), controlPoint1: CGPoint(x: width, y: height - 7.03), controlPoint2: CGPoint(x: width - 7.77, y: height))
path.addLine(to: CGPoint(x: 17.64, y: height))
path.addLine(to: CGPoint(x: 17.64, y: height))
path.addCurve(to: CGPoint(x: 8.69, y: height - 3.56), controlPoint1: CGPoint(x: 14.39, y: height),controlPoint2: CGPoint(x: 11.24, y: height - 1.57))
path.addLine(to: CGPoint(x: 8.79, y: height - 3.46))
path.addCurve(to: CGPoint(x: 0, y: height), controlPoint1: CGPoint(x: 7.27, y: height - 1.27), controlPoint2: CGPoint(x: 3.84, y: height + 0.51))
path.addCurve(to: CGPoint(x: 3.02, y: height - 14.1), controlPoint1: CGPoint(x: 4.06, y: height - 4.22), controlPoint2: CGPoint(x: 3.02, y: height - 9.62))
path.close()
if self.reverted {
let mirrorOverXOrigin: CGAffineTransform = CGAffineTransform(scaleX: -1.0, y: 1.0);
let translate: CGAffineTransform = CGAffineTransform(translationX: width, y: 0);
// Apply these transforms to the path
path.apply(mirrorOverXOrigin)
path.apply(translate)
}
path.fill()
shapeLayer.path = path.cgPath
shapeLayer.rasterizationScale = UIScreen.main.scale
shapeLayer.shouldRasterize = true
if let bubbleLayer = self.bubbleLayer {
self.layer.replaceSublayer(bubbleLayer, with: shapeLayer)
} else {
self.layer.insertSublayer(shapeLayer, at: 0)
}
self.bubbleLayer = shapeLayer
}
shapeLayer.path = path.cgPath
shapeLayer.rasterizationScale = UIScreen.main.scale
shapeLayer.shouldRasterize = true
self.layer.insertSublayer(shapeLayer, at: 0)
self.bubbleLayer?.removeFromSuperlayer()
self.bubbleLayer = shapeLayer
}
your solution cannot work. Draw(_ :) is not called during animation block. It is draw after tableView.endUpdates(), after UITableView ends animation.
Draw(_ :) - I don't think you should use it for your needs at all.
If I can recommend you some solution:
1) In awakeFromNib:
override func awakeFromNib() {
super.awakeFromNib()
self.contentView.backgroundColor = self.shapeColor
self.contentView.layer.cornerRadius = 15
/** make left view and attach it to the left bottom anchors with fixed size and draw into this view the shape of your left arrow***/
self.leftArrowView.isHidden = self.isReverted
/** make right view and attach it to the right bottom anchors with fixed size and draw into this view the shape of your right arrow***/
self.rightArrowView.isHidden = !self.isReverted
}
2) In prepareForReuse:
override func prepareForReuse() {
super.prepareForReuse()
self.leftArrowView.isHidden = self.isReverted
self.rightArrowView.isHidden = !self.isReverted
}
And this should cause your cell will change size smoothly.

How to create dotted step indicator in swift 5(iOS)

I have a requirement like to draw a dotted step indicator in swift 5. I have searched for lot of tutorials on the same but I couldn't get the proper result. I need the step indicator which should be in vertical position(Top to Bottom). I have used the following code but it is coming wrongly when I run the app in iPad.
private func drawLinePath() {
//let linePath = UIBezierPath()
let path = UIBezierPath()
let centerX = self.frame.width / 2.0
let lineHeight = self.frame.height / 10
path.move(to: CGPoint(x: centerX, y: 0))
path.addLine(to: CGPoint(x: centerX, y: lineHeight))
path.move(to: CGPoint(x: centerX, y:lineHeight + 3))
path.addLine(to: CGPoint(x: centerX, y: lineHeight + 5))
path.move(to: CGPoint(x: centerX, y:lineHeight + 8))
path.addLine(to: CGPoint(x: centerX, y: lineHeight + 10))
path.move(to: CGPoint(x: centerX, y:lineHeight + 12))
path.addLine(to: CGPoint(x: centerX, y: lineHeight + 15))
path.move(to: CGPoint(x: centerX, y:lineHeight + 18))
path.addLine(to: CGPoint(x: centerX, y: lineHeight + 21 ))
path.move(to: CGPoint(x: centerX, y:lineHeight + 23))
path.addLine(to: CGPoint(x: centerX, y: lineHeight + 26))
path.move(to: CGPoint(x: centerX, y:lineHeight + 28))
path.addLine(to: CGPoint(x: centerX, y: lineHeight + 31))
path.move(to: CGPoint(x: centerX, y:lineHeight + 33))
path.addLine(to: CGPoint(x: centerX, y: lineHeight + 36))
path.move(to: CGPoint(x: centerX, y:lineHeight + 38))
path.addLine(to: CGPoint(x: centerX, y: lineHeight + 41))
self.path = path.cgPath
}
here is code working perfectly.
func drawLineFromPoint(start : CGPoint, toPoint end:CGPoint, ofColor lineColor: UIColor, inView view:UIView) {
//design the path
let path = UIBezierPath()
path.move(to: start)
path.addLine(to: end)
//design path in layer
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.cgPath
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.strokeColor = lineColor.cgColor
shapeLayer.lineWidth = 4.0
shapeLayer.lineCap = .round
shapeLayer.lineDashPattern = [0.001,16]
shapeLayer.lineDashPhase = 4
view.layer.addSublayer(shapeLayer)
}
func drawLine() {
let frm1: CGRect = img1.frame
let frm2 : CGRect = img2.frame
drawLineFromPoint(start: CGPoint(x: frm1.origin.x + 12, y: frm1.origin.y + 25), toPoint: CGPoint(x: frm1.origin.x + 12, y: frm2.origin.y), ofColor: UIColor.black, inView: self.view)
}
override func viewDidLoad() {
super.viewDidLoad()
drawLine()
}
here is image
For that dotted path you can take UILabel and set text as '......' with your required font size and color. No need to draw any Bezier path. Just use UILabel.
take UIView for dashed line and use below code for line.
extension UIView {
func createDashedLine(from point1: CGPoint, to point2: CGPoint, color: UIColor, strokeLength: NSNumber, gapLength: NSNumber, width: CGFloat) {
let shapeLayer = CAShapeLayer()
shapeLayer.strokeColor = color.cgColor
shapeLayer.lineWidth = width
shapeLayer.lineDashPattern = [strokeLength, gapLength]
let path = CGMutablePath()
path.addLines(between: [point1, point2])
shapeLayer.path = path
layer.addSublayer(shapeLayer)
}}
Now use it like below..
let topPoint = CGPoint(x: vw.frame.midX, y: vw.bounds.minY)
let bottomPoint = CGPoint(x: vw.frame.midX, y: vw.bounds.maxY)
vw.createDashedLine(from: topPoint, to: bottomPoint, color: .lightGray, strokeLength: 4, gapLength: 6, width: 2)
You can use StepIndicator pod for that, you can find example from this link
https://github.com/chenyun122/StepIndicator
let rect = CGRect(origin: CGPoint(x: 0, y: 0), size: CGSize.init(width: 20, height: 40))
let layer = CAShapeLayer()
let path = UIBezierPath(roundedRect: rect, cornerRadius: 4)
layer.path = path.cgPath
layer.strokeColor = UIColor.gray.cgColor
layer.lineDashPattern = [3,3];
layer.backgroundColor = _CLEAR_COLOR.cgColor;
layer.fillColor = _CLEAR_COLOR.cgColor;
viewDottedLine.layer.addSublayer(layer);
Change rect values as per your view and lineDashPattern.
Hope that will work for you.

how to draw UIBezierPaths swift

Here's what I want to do:
with help UIBezierPath i want draw mask like on this link
// Create an image context containing the original UIImage.
let maskWithHole = CAShapeLayer()
let biggerRect = CGRect(x: 0, y: 0, width: withSize.width, height: withSize.height)
let maskPath = UIBezierPath() //UIBezierPath(roundedRect: toRectArray.first!, cornerRadius: 40)
maskPath.move(to: CGPoint(x: biggerRect.minX, y: biggerRect.minY))
maskPath.addLine(to: CGPoint(x: biggerRect.minX, y: biggerRect.maxY))
maskPath.addLine(to: CGPoint(x: biggerRect.maxX, y: biggerRect.maxY))
maskPath.addLine(to: CGPoint(x: biggerRect.maxX, y: biggerRect.minY))
maskPath.addLine(to: CGPoint(x: biggerRect.minX, y: biggerRect.minY))
let smallerRect = CGRect(x: 10, y: 10, width: withSize.width - 10, height: withSize.height - 10)
maskPath.move(to: CGPoint(x: smallerRect.minX, y: smallerRect.minY))
maskPath.addLine(to: CGPoint(x: smallerRect.minX, y: smallerRect.maxY))
maskPath.addLine(to: CGPoint(x: smallerRect.maxX, y: smallerRect.maxY))
maskPath.addLine(to: CGPoint(x: smallerRect.maxX, y: smallerRect.minY))
maskPath.addLine(to: CGPoint(x: smallerRect.minX, y: smallerRect.minY))
maskWithHole.path = maskPath.cgPath
maskWithHole.fillRule = kCAFillRuleEvenOdd
maskWithHole.fillColor = UIColor.orange.cgColor
maskWithHole.opacity = 1.0
it's work i cut inside content of image but want round rect inside when cut like link image.

UIView with UIBezierPath with reversing path

I am trying to give some mask at bottom view using UIBezierPath with addCurve() method.
Expected Result
Current Output
What I have tried is:
viewHeader.backgroundColor = headerColor
let path = UIBezierPath()
let cpoint1 = CGPoint(x: 80, y: 160)
let cpoint2 = CGPoint(x: 280, y: viewHeader.Height + 50)
path.move(to:.init(x: 0, y: viewHeader.Height + 10))
path.addCurve(to: .init(x: viewHeader.Width, y: 205), controlPoint1: cpoint1, controlPoint2: cpoint2)
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.reversing().cgPath
shapeLayer.fillColor = headerColor?.cgColor
shapeLayer.strokeColor = UIColor.black.cgColor
shapeLayer.lineWidth = 1.0
viewHeader.layer.addSublayer(shapeLayer)
I hope it ll work for you, enjoy.
func drawLine() {
let headerColor = UIColor.red
let path = UIBezierPath()
let cpoint1 = CGPoint(x: viewHeader.frame.width/4, y: 160)
let cpoint2 = CGPoint(x: viewHeader.frame.width*3/4, y: viewHeader.frame.height + 50)
path.move(to:.init(x: 0, y: 0))
path.addLine(to:.init(x: 0, y: viewHeader.frame.height - 50))
path.addCurve(to: .init(x: viewHeader.frame.width, y: viewHeader.frame.height - 50), controlPoint1: cpoint1, controlPoint2: cpoint2)
path.addLine(to: CGPoint(x: viewHeader.frame.width, y: 0))
path.addLine(to: CGPoint(x: 0, y: 0))
path.close()
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.reversing().cgPath
shapeLayer.fillColor = headerColor.cgColor
shapeLayer.strokeColor = headerColor.cgColor
shapeLayer.lineWidth = 1.0
viewHeader.layer.addSublayer(shapeLayer)
}

Resources