How to make a UIImage from a UIView (Gradients)

Gradients are an awesome part of app design. They can take a flat colour scheme and make it stand out. I was recently doing some work with a progress bar and wanted to add a custom gradient to it. Unfortunately a UIProgressBar can only be set using a flat colour, or an image. You could use an image for your progress bar however this could lead to alot of work down the line if you end up changing your colour schemes (what resolution was the image? what colours did you use? etc..). This guide will show you how you can create a gradient in code and set it as the image input for a UIProgressBar (and obviously anything else that can take a UIImage).

Screen Shot 2017-12-18 at 22.36.26.png

First things first you need to create a progress bar. Connect this up to your view controller (I called mine progressView). Now before we go any further I want to increase the height of the progress bar so that we can more easily see the gradient. Unfortunately Apple don’t provide us with a way of changing the height of a progress bar so we will have to improvise!

We are going to apply a CGAffine transform to the progress bar that will stretch it in the y direction, making the view taller. I have found through trial and error that the corners of the progress view might look bad (completely awful) so I recommend embedding the progress bar within a UIView (so that we can hide the jaggy edges created by the transform). Select the bar, go to Editor -> Embed In -> View.

Screen Shot 2017-12-18 at 23.02.02.png

I have set my storyboard background colour to green so you can better see the view we are embedding the progress bar in. Next we need to apply some (lovely) auto layout to our storyboard, always make sure you are applying auto layout when creating storyboard views (because it’s a nightmare to come back and fix). I applied the following layout constraints to my storyboard:

View (that we embedded the progress bar in) – Horizontal / Vertical in container & Fixed Height (42), Width (190).

Progress Bar – Horizontal / Vertical in container & Trailing / Leading space to superview (0, 0).

Your storyboard should now be done, there should be no errors and the view should rotate correctly. Next we need to hook up our UIView to the View Controller. Connect up the view and name it something like containerView.  Lets quickly apply our transformation to the progress bar and clean up the edges of the view.

Swift:

//Increase height of progress view
progressView.transform = CGAffineTransform(scaleX: 1, y: 20)

//Round the corners of the progress view (using its container view)
containerView.layer.cornerRadius = 10
containerView.layer.masksToBounds = true

Objective C:

_progressView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1, 20);

_containerView.layer.cornerRadius = 10;
_containerView.layer.masksToBounds = true;

Build & Run the app and you should have something that looks a little like this:

Screen Shot 2017-12-18 at 23.21.53.png

Now we have our progress bar looking view its time to add a gradient. To do this we need to do 3 things:

  • Create a gradient (Layer)
  • Create a UIView to add the gradient to
  • Convert the UIView into a UIImage

First lets make our gradient. We can do this by defining our colours, creating a gradient layer and setting a direction for the gradient. See the code below for how to implement the gradient.

Swift:

let colour1 = UIColor.yellow.cgColor
let colour2 = UIColor.red.cgColor

let gradientLayer = CAGradientLayer()
gradientLayer.frame = containerView.bounds
gradientLayer.colors = [colour1, colour2]
gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)

Objective C:

CAGradientLayer *gradientLayer = [CAGradientLayer layer];

UIColor *primary = [UIColor yellowColor];
UIColor *highlight = [UIColor redColor];

gradientLayer.frame = _containerView.bounds;
gradientLayer.colors = @[(id)primary.CGColor, (id)highlight.CGColor];
gradientLayer.startPoint = CGPointMake(0.0, 0.5);
gradientLayer.endPoint = CGPointMake(1.0, 0.5);

Now we have our gradient, lets create a view to display the gradient on (as it is currently just a layer).

Swift:

let gradientView = UIView(frame: containerView.bounds)
        gradientView.layer.addSublayer(gradientLayer)

Objective C:

UIView *gradientView = [[UIView alloc] initWithFrame:_containerView.bounds];
    [gradientView.layer addSublayer:gradientLayer];

Now we have a UIView that can display our gradient. Lets convert it to a UIImage so that we can display it on our progress bar.

Swift:

let renderer = UIGraphicsImageRenderer(size: gradientView.bounds.size)
let image = renderer.image { ctx in
            gradientView.drawHierarchy(in: gradientView.bounds, afterScreenUpdates: true)
}

progressView.progressImage = image

Objective C:

UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:gradientView.bounds.size];
UIImage *gradientImage = [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull rendererContext) {
        [gradientView drawViewHierarchyInRect:gradientView.bounds afterScreenUpdates:true];
    }];

_progressView.progressImage = gradientImage;

So with this code we take our UIView and use UIGraphicsImageRenderer to render an image of the view. This code can be ran in the viewDidLoad (although it ideally should be put in the viewWillAppear). Lets take a look at the result!Screen Shot 2017-12-19 at 21.24.59.png

Awesome! now we have a fully customisable gradient image, all you need to do is change the colour variables and you will have changed the colour of your progress bar, lets take a look at some more examples!

gradients.png

There are many possibilities here, you can do this sort of thing with an SMPageControl (see below).

Screen Shot 2017-12-19 at 22.38.08.png

Moving forwards you could rework the code I have given you into a method so that you can quickly make a gradient, a gradient view or a gradient image. Hopefully you find this useful!

I have included links to the projects I used to make this guide here:

Swift Project Files (Swift 4)

Objective C Files

And you can read my previous guide about neatly organising your cocoa-pod acknowledgement files here.

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s