Home » Swift » How to procedurally draw rectangle / lines in swift using CGContext

How to procedurally draw rectangle / lines in swift using CGContext

Posted by: admin November 30, 2017 Leave a comment

Questions:

I’ve been trawling the internet for days trying to find the simplest code examples on how to draw a rectangle or lines procedurally in Swift. I have seen how to do it by overriding the DrawRect command. I believe you can create a CGContext and then drawing into an image, but I’d love to see some simple code examples. Or is this a terrible approach? Thanks.

class MenuController: UIViewController 
{

    override func viewDidLoad() 
    {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        self.view.backgroundColor = UIColor.blackColor()

        var logoFrame = CGRectMake(0,0,118,40)
        var imageView = UIImageView(frame: logoFrame)
        imageView.image = UIImage(named:"Logo")
        self.view.addSubview(imageView)

        //need to draw a rectangle here
    }
}
Answers:

Here’s an example that creates a custom UIImage containing a transparent background and a red rectangle with lines crossing diagonally through it.

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad();

        let imageSize = CGSize(width: 200, height: 200)
        let imageView = UIImageView(frame: CGRect(origin: CGPoint(x: 100, y: 100), size: imageSize))
        self.view.addSubview(imageView)
        let image = drawCustomImage(imageSize)
        imageView.image = image
    }
}

func drawCustomImage(size: CGSize) -> UIImage {
    // Setup our context
    let bounds = CGRect(origin: CGPoint.zeroPoint, size: size)
    let opaque = false
    let scale: CGFloat = 0
    UIGraphicsBeginImageContextWithOptions(size, opaque, scale)
    let context = UIGraphicsGetCurrentContext()

    // Setup complete, do drawing here
    CGContextSetStrokeColorWithColor(context, UIColor.redColor().CGColor)
    CGContextSetLineWidth(context, 2.0)

    CGContextStrokeRect(context, bounds)

    CGContextBeginPath(context)
    CGContextMoveToPoint(context, CGRectGetMinX(bounds), CGRectGetMinY(bounds))
    CGContextAddLineToPoint(context, CGRectGetMaxX(bounds), CGRectGetMaxY(bounds))
    CGContextMoveToPoint(context, CGRectGetMaxX(bounds), CGRectGetMinY(bounds))
    CGContextAddLineToPoint(context, CGRectGetMinX(bounds), CGRectGetMaxY(bounds))
    CGContextStrokePath(context)

    // Drawing complete, retrieve the finished image and cleanup
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return image
}

Questions:
Answers:

An updated answer using Swift 3.0

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad();

        let imageSize = CGSize(width: 200, height: 200)
        let imageView = UIImageView(frame: CGRect(origin: CGPoint(x: 100, y: 100), size: imageSize))
        self.view.addSubview(imageView)
        let image = drawCustomImage(size: imageSize)
        imageView.image = image
    }
}

func drawCustomImage(size: CGSize) -> UIImage? {
    // Setup our context
    let bounds = CGRect(origin: CGPoint.zero, size: size)
    let opaque = false
    let scale: CGFloat = 0
    UIGraphicsBeginImageContextWithOptions(size, opaque, scale)
    guard let context = UIGraphicsGetCurrentContext() else { return nil }

    // Setup complete, do drawing here
    context.setStrokeColor(UIColor.red.cgColor)
    context.setLineWidth(5.0)

    // Would draw a border around the rectangle
    // context.stroke(bounds)

    context.beginPath()
    context.move(to: CGPoint(x: bounds.maxX, y: bounds.minY))
    context.addLine(to: CGPoint(x: bounds.minX, y: bounds.maxY))
    context.strokePath()

    // Drawing complete, retrieve the finished image and cleanup
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return image
}

let imageSize = CGSize(width: 200, height: 200)
let imageView = UIImageView(frame: CGRect(origin: CGPoint(x: 100, y: 100), size: imageSize))
let image = drawCustomImage(size: imageSize)
imageView.image = image

Questions:
Answers:

I used the accepted answer to draw lines in a Tic Tac Toe game when one of the players won. Thanks, good to know that it worked. Unfortunately, I ran into some problems getting it to work on different sizes of iPhones and iPads simultaneously. That’s probably something that should have been addressed. Basically what I’m saying is that it might not actually be worth the trouble of all that code, depending on your case.

My alternate solution is to simply make customized, better looking line in Photoshop and then load it with UIImageView. For me this was MUCH simpler, runs better, and looks better. Obviously it really depends on what you need it for.

Steps:

1: Download or create an image (preferably saved as .PNG)

2: Drag it into your project

3: Drag a UIImage View into your storyboard

4: Click on the Image View and select the image in the attributes inspector

5: Ctrl click and drag the Image View to your .swift file to declare an Outlet

6: Set the autolayout constraints so it works on ALL devices EASILY

Animating, rotating, and transforming image views on and off the screen is also arguably easier

To change the image:

yourImageViewOutletName.image = UIImage(named: "ImageNameHere")