Wednesday, June 1, 2011

How to create a UIImage with a gradient from one or more UIColor

I recently needed to create a very specific progress bar not provided "as is" in the iOS SDK.
"The progress bar have an evolving background, a text label in foreground and an animation as the download/upload progresses. It must also be possible to tap on the progress bar like on a button.".

Solving this issue is pretty simple actually; you only need to use two overlapping buttons, one for the background and another for both the text label and the progression image. The latter has a clearColor background, at least for the "not yet filled" part of the progress image of course.

The point of this article is to provide the piece of code which allowed me to create this progress image set on the foreground button.

/* Create a Core Graphics Image context with the width and height of the progress bar button
    and push this context on the stack.  At this point, the image is clearColored. */

    UIGraphicsBeginImageContext(CGSizeMake(width, height));             
    CGContextRef context = UIGraphicsGetCurrentContext();           
    UIGraphicsPushContext(context);                                                         


/* Set the color to use for the fillRect method. Here we want a blue filling. */
    CGContextSetFillColorWithColor(context, [UIColor blueColor].CGColor);
/* Fill the Core Graphics Image with the color defined above given 'progress' the percent value as float between 0  and 1. */
    CGContextFillRect(context, CGRectMake(0, 0, width * progress, height));


/* Now we can remove the graphic context from the stack, retrieve the freshly created UIImage and of course, release the Core Graphics image context we created at first. */
        UIGraphicsPopContext();
        UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();


/* Set the new background. */
    [myProgressButton setBackgroundImage:outputImage forState:UIControlStateNormal];