I am working on designing custom UIimageview in swift. I want to create a UIimageview using beizerpath similar to this
The coding should be in swift. Any help is
I'm using something like this and it worked fine, you can add any thing you want to the view
import UIKit
class CustomView: UIView {
// Only override draw() if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func draw(_ rect: CGRect) {
// Drawing code
// Get Height and Width
let layerHeight = layer.frame.height
let layerWidth = layer.frame.width
// Create Path
let bezierPath = UIBezierPath()
// Points
let pointA = CGPoint(x: 0, y: 0)
let pointB = CGPoint(x: layerWidth, y: 0)
let pointC = CGPoint(x: layerWidth, y: layerHeight)
let pointD = CGPoint(x: 0, y: layerHeight*2/3)
// Draw the path
bezierPath.move(to: pointA)
bezierPath.addLine(to: pointB)
bezierPath.addLine(to: pointC)
bezierPath.addLine(to: pointD)
bezierPath.close()
// Mask to Path
let shapeLayer = CAShapeLayer()
shapeLayer.path = bezierPath.cgPath
layer.mask = shapeLayer
}
}
Create a CAShapeLayer
and supply it a path
and a fillColor
:
@IBDesignable
public class AngleView: UIView {
@IBInspectable public var fillColor: UIColor = .blue { didSet { setNeedsLayout() } }
var points: [CGPoint] = [
.zero,
CGPoint(x: 1, y: 0),
CGPoint(x: 1, y: 1),
CGPoint(x: 0, y: 0.5)
] { didSet { setNeedsLayout() } }
private lazy var shapeLayer: CAShapeLayer = {
let _shapeLayer = CAShapeLayer()
self.layer.insertSublayer(_shapeLayer, at: 0)
return _shapeLayer
}()
override public func layoutSubviews() {
shapeLayer.fillColor = fillColor.cgColor
guard points.count > 2 else {
shapeLayer.path = nil
return
}
let path = UIBezierPath()
path.move(to: convert(relativePoint: points[0]))
for point in points.dropFirst() {
path.addLine(to: convert(relativePoint: point))
}
path.close()
shapeLayer.path = path.cgPath
}
private func convert(relativePoint point: CGPoint) -> CGPoint {
return CGPoint(x: point.x * bounds.width + bounds.origin.x, y: point.y * bounds.height + bounds.origin.y)
}
}
Now, I made this designable (so if you put it in a separate framework target, you can add this view right in your storyboard and see it rendered there). It still works if you're not using storyboards. It just can be convenient to do so:
I also used relative coordinates (with values ranging from zero to one) and have a method to convert those to actual coordinates, but you can hard code your coordinates if you want. But using this as values from zero to one, you have an angular view that can participate in auto-layout without needing to worry about changing specific coordinate values.
Finally, minor things that might seem trivial, but I construct the path
in layoutSubviews
: That way, as the view changes size (whether via auto-layout or programmatic changes), the view will be correctly re-rendered. Likewise, by using didSet
for fillColor
and points
, if you change either of those, the view will be re-rendered for you.
Feel free to change this as you see fit, but hopefully this illustrates the basic idea of just having a CAShapeLayer
with a custom path
.
If you use insertSublayer
, you can then combine this with other subviews of the AngleView, e.g.: