I have a UIBezierPath
, and I ultimately I need a UIImageView
from it. Right now I'm trying to first create a UIImage
, and then a UIImageView
from that.
I'm working in swift, and I have looked at similar questions, and the answers either don't work or produce a shape rather than a curve. My beziers represent sketches as opposed to actual shapes. I don't want the bezier closed, which is what UIImage.shapeImageWithBezierPath()
does. This last solution is the only one which has actually encapsulated the full curve. All the other solutions either produce fragments or don't show up at all.
The end goal is to create a CollectionView
with these curves as items in the list, meaning that I ultimately have to put UIBeziers
into CollectionViewCells
.
Thanks in advance.
If you want UIImage
(which you can use with UIImageView
), you can use UIGraphicsImageRenderer
:
private func image(with path: UIBezierPath, size: CGSize) -> UIImage {
return UIGraphicsImageRenderer(size: size).image { _ in
UIColor.blue.setStroke()
path.lineWidth = 2
path.stroke()
}
}
That was introduced in iOS 10. If you need to support earlier iOS versions, you can use the UIGraphicsGetImageFromCurrentImageContext
:
private func image(with path: UIBezierPath, size: CGSize) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(size, false, 0)
UIColor.blue.setStroke()
path.lineWidth = 2
path.stroke()
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
Alternatively, you can bypass the UIImage
if you want, and just define a UIView
subclass with a CAShapeLayer
:
@IBDesignable
class ShapeView: UIView {
@IBInspectable var lineWidth: CGFloat = 1 { didSet { shapeLayer.lineWidth = lineWidth } }
@IBInspectable var strokeColor: UIColor = #colorLiteral(red: 0, green: 0, blue: 1, alpha: 1) { didSet { shapeLayer.strokeColor = strokeColor.cgColor } }
@IBInspectable var fillColor: UIColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 0) { didSet { shapeLayer.fillColor = fillColor.cgColor } }
var path: UIBezierPath? { didSet { shapeLayer.path = path?.cgPath } }
private let shapeLayer = CAShapeLayer()
override init(frame: CGRect) {
super.init(frame: frame)
configure()
}
convenience init() {
self.init(frame: .zero)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
configure()
}
/// Add and configure the view.
///
/// Add and configure shape.
private func configure() {
layer.addSublayer(shapeLayer)
shapeLayer.strokeColor = self.strokeColor.cgColor
shapeLayer.fillColor = self.fillColor.cgColor
shapeLayer.lineWidth = self.lineWidth
}
// just add some path so if you used this in IB, you'll see something
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
shapeLayer.path = UIBezierPath(ovalIn: bounds.insetBy(dx: lineWidth / 2, dy: lineWidth / 2)).cgPath
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With