I have drawn a very simple path using a UIBezierPath and a custom UIView subclass but for some reason, a border appears around the bounds of the view and I cannot seem to get rid of it or see why it was created.
I used this code:
private override func draw(_ rect: CGRect) {
let path = UIBezierPath(rect: CGRect(x: 15, y: 15, width: 300, height: 300))
path.move(to: CGPoint(x: 100, y: 100))
path.addLine(to: CGPoint(x: 150, y: 150))
path.addLine(to: CGPoint(x: 100, y: 200))
path.addLine(to: CGPoint(x: 150, y: 250))
path.lineWidth = 25.0
UIColor.darkGray.setStroke()
path.stroke()
}
and it gave this result... (the border should not be there, only the zig-zag line)
Any help please?
You're creating that rectangle by
let path = UIBezierPath(rect: CGRect(x: 15, y: 15, width: 300, height: 300))
you just need to do
let path = UIBezierPath()
You are initialising the path with a rect, which gets drawn with the stroke.
Just replace your first line with this:
let path = UIBezierPath()
Related
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.
I using Swift to creating a custom button in a phone UI and need to clip the bottom of the button in the convex like shape.
The problem was it should be perfect and the bottom curve should match the bigger button
I tried different approaches but it's not getting the perfect result.
Using rounded corners
if buttonDirection == 0 {
path = UIBezierPath(roundedRect: rect, byRoundingCorners:[UIRectCorner.topLeft, .topRight], cornerRadii: CGSize(width: self.bounds.width/2, height: 0))
path.close()
}
Create whole path without rounded curve using QuardCurve // still bottom part not inverse curve plus corner are also not smooth as 1
if buttonDirection == 0 {
//path = UIBezierPath(roundedRect: rect, byRoundingCorners:[UIRectCorner.topLeft, .topRight], cornerRadii: CGSize(width: self.bounds.width/2, height: 0))
//path.close()
let curve = UIBezierPath()
curve.move(to: CGPoint(x: 0, y: self.bounds.height))
curve.addLine(to:CGPoint(x: 0, y: self.bounds.width/3))
curve.addQuadCurve(to: CGPoint(x: self.bounds.width, y: self.bounds.width/3), controlPoint: CGPoint(x: self.bounds.width/2, y: -5))
curve.addLine(to: CGPoint(x: self.bounds.width, y: self.bounds.height))
curve.addQuadCurve(to: CGPoint(x: 0, y: self.bounds.height), controlPoint: CGPoint(x: self.bounds.width/2, y: self.bounds.width - 10))
UIColor.black.setFill()
curve.fill()
}
Create the path from 1 and then just Clip QuardCurve
if buttonDirection == 0 {
path = UIBezierPath(roundedRect: rect, byRoundingCorners:[UIRectCorner.topLeft, .topRight], cornerRadii: CGSize(width: self.bounds.width/2, height: 0))
path.close()
path.move(to: CGPoint(x: 0, y: self.bounds.height))
path.addQuadCurve(to: CGPoint(x: self.bounds.width, y: self.bounds.height), controlPoint: CGPoint(x: self.bounds.width/2, y: self.bounds.height/2))
path.addClip()
UIColor.black.setFill()
path.fill()
}
I tried many other things also but not getting the result, What I wanted is simply clip the bottom curve from the 1st path, Like how to cut one path from another (After reading apples doc I come to know I can use path.reverse() also )
here are all buttons in one pic and when you click the button say vol + its changes the colour
PS Edited the original question, as images were confusing, and I found one solution but still want to know if there is a better solution with one path and smooth edges.
Below method worked but if someone has better solution do post.
Basically what I am doing here is first clipping the whole button with the bottom part as convex, using addLines and Quardcurve in the bottom and after that creating new path using bezier roundedRect initialization with top-right and top-left corner.
if buttonDirection == 0 {
let curve = UIBezierPath()
curve.move(to: CGPoint(x: 0, y: self.bounds.height))
curve.addLine(to: CGPoint(x: 0, y: 0))
curve.addLine(to: CGPoint(x: self.bounds.width, y: 0))
curve.addLine(to: CGPoint(x: self.bounds.width, y: self.bounds.height))
curve.addQuadCurve(to: CGPoint(x: 0, y: self.bounds.height), controlPoint: CGPoint(x: self.bounds.width/2, y: self.bounds.height - self.bounds.height/4))
curve.close()
curve.addClip()
path = UIBezierPath(roundedRect: rect, byRoundingCorners:[UIRectCorner.topLeft, .topRight], cornerRadii: CGSize(width: self.bounds.width/2, height: 0))
path.close()
}
How do i design a UIView whose all 4 corners have different corner radius. So, UIView with its top right corner radius of 20, top left corner radius of 30, bottom left corner radius of 10 and bottom right corner radius of 20
I want to add different cornerRadius to Viw Container shown in image.
using UIBEZIER method cuts off the share comment and like portion.
viw Container is pinned to cell
You can use this UIView extension. It will create and apply a mask layer according to your radius values.
extension UIView {
func applyRadiusMaskFor(topLeft: CGFloat = 0, bottomLeft: CGFloat = 0, bottomRight: CGFloat = 0, topRight: CGFloat = 0) {
let path = UIBezierPath()
path.move(to: CGPoint(x: bounds.width - topRight, y: 0))
path.addLine(to: CGPoint(x: topLeft, y: 0))
path.addQuadCurve(to: CGPoint(x: 0, y: topLeft), controlPoint: .zero)
path.addLine(to: CGPoint(x: 0, y: bounds.height - bottomLeft))
path.addQuadCurve(to: CGPoint(x: bottomLeft, y: bounds.height), controlPoint: CGPoint(x: 0, y: bounds.height))
path.addLine(to: CGPoint(x: bounds.width - bottomRight, y: bounds.height))
path.addQuadCurve(to: CGPoint(x: bounds.width, y: bounds.height - bottomRight), controlPoint: CGPoint(x: bounds.width, y: bounds.height))
path.addLine(to: CGPoint(x: bounds.width, y: topRight))
path.addQuadCurve(to: CGPoint(x: bounds.width - topRight, y: 0), controlPoint: CGPoint(x: bounds.width, y: 0))
let shape = CAShapeLayer()
shape.path = path.cgPath
layer.mask = shape
}
}
Example usage:
let view = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
view.backgroundColor = .red
view.applyRadiusMaskFor(topLeft: 80, bottomLeft: 40, bottomRight: 30, topRight: 60)
Result: Radius applied image
I have an application with some buttons. I want to create a arc shape button like the following image
How can I do it? I use the following code to achieve this.
button.layer.cornerRadius = button.bounds.size.height
and
button.layer.cornerRadius = 0.5*button.bounds.size.height
I also tried this with the using of width
button.layer.cornerRadius = button.bounds.size.width
and
button.layer.cornerRadius = 0.5*button.bounds.size.width
How can I do it? Please someone help me to solve this.
To create arc shape you need to use UIBezierPath
please read apple's UIBezierPath_class Document.
They have mention method for create arc shape.
Creates and returns a new UIBezierPath object initialized with an arc of a circle.
For constructing the path
Appends an arc to the receiver’s path.
You can also Refer Core Graphics Tutorial Part 1 With Example and search with arc keyword on browser you will redirect to arc shape on the page.
Another image posted by #Jack in above comments and asked help, here is the image:
I couldn't answer him as comment, so pasting my playground here instead.
let shapeView = UIView(frame: CGRect(x: 0, y: 0, width: 360, height: 60))
let shapeSize = shapeView.frame.size
shapeView.backgroundColor = UIColor.white
let path = CGMutablePath()
path.move(to: CGPoint.zero)
let curveWidthOneFourth = shapeSize.width / 4
let curveHeight = shapeSize.height * 0.2
path.addCurve(to: CGPoint(x: curveWidthOneFourth * 2, y: curveHeight), control1: .zero, control2: CGPoint(x: curveWidthOneFourth, y: curveHeight))
path.addCurve(to: CGPoint(x: shapeSize.width, y: 0), control1: CGPoint(x: curveWidthOneFourth * 3, y: curveHeight), control2: CGPoint(x: shapeSize.width, y: 0))
path.addLine(to: CGPoint(x: shapeSize.width, y: shapeSize.height))
path.addLine(to: CGPoint(x: 0, y: shapeSize.height))
path.addLine(to: CGPoint.zero)
And add our path to a view's layer:
let layer = CAShapeLayer()
layer.path = path
layer.fillColor = UIColor.red.cgColor
shapeView.layer.addSublayer(layer)
Encountered a similar task today, I used CGMutableShape instead of UIBezierPath because I was required to animation the shape.
Anyways, to understand the shape I divided the shape into 6 parts (lines & curves):
Base UIView to draw our shape in
let shapeView = UIView(frame: CGRect(x: 16, y: 16, width: 100, height: 44))
shapeView.backgroundColor = UIColor.lightGray
self.view.addSubview(shapeView)
Actual shape and its path
let path = CGMutablePath()
path.move(to: CGPoint(x: 10, y: 0)) // Move path to beginning of part-1
// Draw above divided parts
path.addLine(to: CGPoint(x: 90, y: 0)) // Part-1
path.addCurve(to: CGPoint(x: 95, y: 22), control1: CGPoint(x: 93, y: 6.6), control2: CGPoint(x: 95, y: 14)) // Part-2
path.addCurve(to: CGPoint(x: 90, y: 44), control1: CGPoint(x: 95, y: 30), control2: CGPoint(x: 93, y: 37)) // Part-3
path.addLine(to: CGPoint(x: 10, y: 44)) // Part-4
path.addCurve(to: CGPoint(x: 5, y: 22), control1: CGPoint(x: 7, y: 37), control2: CGPoint(x: 5, y: 30)) // Part-5
path.addCurve(to: CGPoint(x: 10, y: 0), control1: CGPoint(x: 5, y: 14), control2: CGPoint(x: 6, y: 6.6)) // Part-6
let arcLayer = CAShapeLayer()
arcLayer.path = path
arcLayer.fillColor = UIColor.gray.cgColor
shapeView.layer.insertSublayer(arcLayer, at: 0)
I have an app in which there are so many popover and every popover so many objects like UIButtons, UILable,UITableView.
Now I want to create view like popover using UIBezierpathswith upside arrow.
How can I do that in a UIView?
don't want to any third party tool.
Any help will be appreciated.
Check my answer from link here and just change the point values according to your need or path.
Hope it will help you.
I am late but could be helpful to someone
func drawPopoverRadius(text: String) -> UIView {
let layer = CAShapeLayer()
let path = UIBezierPath()
path.move(to: .zero)
path.addLine(to: CGPoint(x: 51, y: 0))
path.addLine(to: CGPoint(x: 51, y: 48))
path.addLine(to: CGPoint(x: 51/2 - 4, y: 48))
path.addLine(to: CGPoint(x: 51/2, y: 52))
path.addLine(to: CGPoint(x: 51/2 + 4, y: 48))
path.addLine(to: CGPoint(x: 0, y: 48))
path.close()
layer.path = path.cgPath
layer.fillColor = UIColor.gray.cgColor
layer.anchorPoint = .zero
layer.name = "popover"
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 51, height: 52))
label.clipsToBounds = false
label.numberOfLines = 0
label.font = NunitoSans.regular.font(size: 14)
label.textColor = .white
label.text = text
label.layer.addSublayer(layer)
return label
}