Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to procedurally draw rectangle / lines in swift using CGContext

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
    }
}
like image 950
iphaaw Avatar asked Aug 10 '14 15:08

iphaaw


3 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(size: imageSize)
        imageView.image = image
    }
}

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

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

    context.stroke(bounds)

    context.beginPath()
    context.move(to: CGPoint(x: bounds.minX, y: bounds.minY))
    context.addLine(to: CGPoint(x: bounds.maxX, y: bounds.maxY))
    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!
}
like image 172
Wolf McNally Avatar answered Oct 18 '22 03:10

Wolf McNally


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
like image 9
KFDoom Avatar answered Oct 18 '22 01:10

KFDoom


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")
like image 3
mothy Avatar answered Oct 18 '22 02:10

mothy