Reputation: 83
I don't have experience in Core Graphics but I need to draw a dynamic uiimage that look like these:
(Actually I want the grey area to be clear. So the red color will look like floating)
This is the code I tried:
public extension UIImage {
public convenience init?(color: UIColor, size: CGSize = CGSize(width: 27, height: 5), isWhole: Bool = true) {
let totalHeight: CGFloat = 5.0
let topRectHeight: CGFloat = 1.0
//if (isWhole) {
let topRect = CGRect(origin: .zero, size: CGSize(width: size.width, height: topRectHeight))
UIGraphicsBeginImageContextWithOptions(topRect.size, false, 0.0)
color.setFill()
UIRectFill(topRect)
let bottomRect = CGRect(origin: CGPoint(x: 0, y: topRectHeight), size: CGSize(width: size.width, height: totalHeight - topRectHeight))
UIGraphicsBeginImageContextWithOptions(bottomRect.size, false, 0.0)
UIColor.blue.setFill()
UIRectFill(bottomRect)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
guard let cgImage = image?.cgImage else { return nil }
self.init(cgImage: cgImage)
}
Upvotes: 2
Views: 5607
Reputation: 433
Here is example you can have first image if you set isWhole property to false and have second image if you set it to true. You can paste this code in viewDidLoad to test and play with it.
var isWhole = false
UIGraphicsBeginImageContextWithOptions(CGSize.init(width: 27, height: 5), false,0.0)
var context = UIGraphicsGetCurrentContext()
context?.setFillColor(UIColor.red.cgColor)
if(context != nil){
if(isWhole){
context?.fill(CGRect(x: 0, y: 0, width: 27, height: 2.5))
}
else{
context?.fill(CGRect(x: 0, y: 0, width: 13.5, height: 2.5))
}
context?.setFillColor(UIColor.gray.cgColor)
context?.fill(CGRect(x: 0, y: 2.5, width: 27, height: 2.5))
}
let newImage = UIGraphicsGetImageFromCurrentImageContext()
var imageView = UIImageView(frame: CGRect(x: 100, y: 200, width: 27, height: 5))
imageView.image = newImage
self.view.addSubview(imageView)
UIGraphicsEndImageContext()
If you need your red rectangle to be with rounder corners just change fill(rect:CGRect) with path like this:
if(isWhole){
context?.addPath(CGPath(roundedRect: CGRect(x: 0, y: 0, width: 27, height: 2.5), cornerWidth: 1, cornerHeight: 1, transform: nil))
context?.fillPath()
}
Upvotes: 1
Reputation:
I know you said in your comments that you can't use UIViews
, but what you want "looks" easily done through views. Why not do that, then simply turn it into a UIImage
?
override func viewDidLoad() {
super.viewDidLoad()
let imageContainer = UIView(frame: CGRect(x: 30, y: 40, width: 110, height: 60))
imageContainer.backgroundColor = view.backgroundColor
view.addSubview(imageContainer)
let redView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 30))
redView.backgroundColor = UIColor.red
let grayView = UIView(frame: CGRect(x: 10, y: 30, width: 100, height: 30))
grayView.backgroundColor = UIColor.gray
imageContainer.addSubview(redView)
imageContainer.addSubview(grayView)
let imageView = UIImageView(frame: CGRect(x: 100, y: 140, width: 200, height: 200))
imageView.contentMode = .scaleAspectFit
imageView.image = createImage(imageContainer)
view.addSubview(imageView)
}
func createImage(_ view: UIView) -> UIImage {
UIGraphicsBeginImageContextWithOptions(
CGSize(width: view.frame.width, height: view.frame.height), true, 1)
view.layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
Upvotes: 1
Reputation: 1149
I'd recommend creating two paths in the first context that you create, i.e.
let topPath = UIBezierPath(rect: topRect)
color.setFill()
topPath.fill()
let bottomPath = UIBezierPath(rect: bottomRect)
UIColor.blue.setFill()
bottomPath.fill()
Then you can get the image from the current context.
Upvotes: 0