Search code examples
iosswiftcore-graphics

Swift 3 draw uiimage programmatically


I don't have experience in Core Graphics but I need to draw a dynamic uiimage that look like these:

left

whole

(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)
    }

Solution

  • 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()
        }