Search code examples
iosswiftoptimizationcore-graphicscgcontext

How to fill a UIView with an alternating stripe pattern programmatically using Swift?


I can achieve an alternating stripe pattern fill using an image with UIColor(patternImage: UIImage(named: "pattern.png")).

However, how can I achieve an alternating stripe pattern fill drawing it programmatically with some simple compact code?

Here are two examples I'd like to achieve.

Question

Using code, how do I fill a UIView with different alternating color stripes using Swift?

(1) a two color alternating pattern running top to bottom (90 degrees)?

(2) a three color alternating pattern running top left to bottom right (45 degrees)?

enter image description here


Solution

  • Filling a view with a stripe pattern with two, three or more color stripes with adjustable stripe widths and rotation can be achieved with the below code. This code gives a three colour stripe pattern shown in the example image below.

    Steps:

    1. Add the below code to ViewController.swift
    2. Add a UIView to Storyboard.
    3. Add new alignment contstraints to the UIView on the Storyboard; Horizontally in Container = 0, Vertically in Container = 0.
    4. In the Identity Inspector, set the UIView custom class to 'colorStripesView'.
    5. Connect the UIView on the Storyboard to the viewPattern IBOutlet in the code.

    Code:

        ////   ViewController.swift
    
        //// 1. Add the below code to ViewController.swift
        //// 2. Add a UIView to Storyboard.
        //// 3. Add new alignment contstraints to the UIView on the Storyboard; Horizontally in Container = 0, Vertically in Container = 0.
        //// 4. In the Identity Inspector, set the UIView custom class to 'colorStripesView'.
        //// 5. Connect the UIView on the Storyboard to the viewPattern IBOutlet in the code.
    
        import UIKit
    
        class ViewController: UIViewController {
            @IBOutlet weak var viewPattern: UIView!
    
            override func viewDidLoad() {
                super.viewDidLoad()
    
                //// Extend width and height constraints by factor of 2 for viewPattern rotation.
                let widthConstraint = NSLayoutConstraint(item: viewPattern, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: (max(view.bounds.height, view.bounds.width)*2))
                viewPattern.addConstraint(widthConstraint)
                let heightConstraint = NSLayoutConstraint(item: viewPattern, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: (max(view.bounds.height, view.bounds.width)*2))
                viewPattern.addConstraint(heightConstraint)
    
                //// Rotate pattern 0 degrees - vertical.
                //viewPattern.transform = CGAffineTransformMakeRotation(CGFloat(M_PI*0/180))
                //// Rotate pattern 45 degrees - diagonal top right to bottom left.
                //viewPattern.transform = CGAffineTransformMakeRotation(CGFloat(M_PI*45/180))
                //// Rotate pattern 90 degrees - horizontal.
                //viewPattern.transform = CGAffineTransformMakeRotation(CGFloat(M_PI*90/180))
                //// Rotate pattern 135 degrees - diagonal top left to bottom right.
                viewPattern.transform = CGAffineTransformMakeRotation(CGFloat(M_PI*135/180))
    
                //// Set view color
                viewPattern.backgroundColor = UIColor.clearColor()
            }
    
            override func didReceiveMemoryWarning() {
                super.didReceiveMemoryWarning()
            }
        }
    
        class colorStripesView: UIView {
            override func drawRect(rect: CGRect) {
                //// Set pattern tile colors width and height; adjust the color width to adjust pattern.
                let color1 = UIColor(red: 255/255, green: 255/255, blue: 10/255, alpha: 1.0)
                let color1Width: CGFloat = 10
                let color1Height: CGFloat = 10
    
                let color2 = UIColor(red: 0/255, green: 0/255, blue: 254/255, alpha: 1.0)
                let color2Width: CGFloat = 10
                let color2Height: CGFloat = 10
    
                let color3 = UIColor(red: 0/255, green: 128/255, blue: 128/255, alpha: 1.0)
                let color3Width: CGFloat = 10
                let color3Height: CGFloat = 10
    
                //// Set pattern tile orientation vertical.
                let patternWidth: CGFloat = (color1Width + color2Width + color3Width)
                let patternHeight: CGFloat = min(color1Height, color2Height, color3Height)
    
                //// Set pattern tile size.
                let patternSize = CGSize(width: patternWidth, height: patternHeight)
    
                //// Draw pattern tile
                let context = UIGraphicsGetCurrentContext()
                UIGraphicsBeginImageContextWithOptions(patternSize, false, 0.0)
    
                let color1Path = UIBezierPath(rect: CGRect(x: 0, y: 0, width: color1Width, height: color1Height))
                color1.setFill()
                color1Path.fill()
    
                let color2Path = UIBezierPath(rect: CGRect(x: color1Width, y: 0, width: color2Width, height: color2Height))
                color2.setFill()
                color2Path.fill()
    
                let color3Path = UIBezierPath(rect: CGRect(x: color1Width + color2Width, y: 0, width: color3Width, height: color3Height))
                color3.setFill()
                color3Path.fill()
    
                let image = UIGraphicsGetImageFromCurrentImageContext()
                UIGraphicsEndImageContext()
    
                //// Draw pattern in view
                UIColor(patternImage: image).setFill()
                CGContextFillRect(context, rect)
            }
        }
    

    Simulator:

    enter image description here