3
votes

I know of several ways of adding background gradients to UIView. I was wondering what is the most efficient and scalable way of doing so, and why? Here are the techniques I've used:

  • Create subview of UIView and overwrite the drawRect, where I draw the gradient in current context.

    a. When using the above gradient create it with the bounds of view I want to decorate and insert this background gradient as first subview, i.e. – insertSubview:atIndex:

    b. After I get the background gradient view from above, I render it in image context and use it as background image, i.e.

    UIGraphicsBeginImageContext(gradView.bounds.size);
    [gradView.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *gradientImg = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    UIColor *background = [UIColor colorWithPatternImage:gradientImg];
    self.view.backgroundColor = background;
    
  • Create stretchable PNG and use that to decorate view background. Technique is very similar to the way you decorate UIButton.

    -(UIColor *)backgroundColor:(CGRect)frame
    {
        UIImage *bg = [UIImage imageNamed:@"background_23x36"];
        bg = [bg resizableImageWithCapInsets:UIEdgeInsetsMake(0.0, 11.0, 0.0, 11.0)];
        UIGraphicsBeginImageContextWithOptions(frame.size, YES, [[UIScreen mainScreen] scale]);
        [bg drawInRect:frame];
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return [UIColor colorWithPatternImage:image];
    }
    
  • Create subview of UIView but instead of overwriting the drawRect, use CAGradientLayer. Similar to http://nscookbook.com/2013/04/recipe-20-using-cagradient-layer-in-a-custom-view/

So what is most efficient and scalable way to add gradient as a background?

2
I'd do it in drawRect of the view. Using CGGradientFogmeister

2 Answers

9
votes

As Fogmeister suggested above, do it in the drawRect: method of your UIView subclass.

- (void)drawRect:(CGRect)rect
{
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = UIGraphicsGetCurrentContext();

    NSArray *gradientColors = [NSArray arrayWithObjects:(id) [UIColor redColor].CGColor, [UIColor yellowColor].CGColor, nil];

    CGFloat gradientLocations[] = {0, 0.50, 1};
    CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef) gradientColors, gradientLocations);

    CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
    CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));

    CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
    CGGradientRelease(gradient);
    CGColorSpaceRelease(colorSpace);
}
0
votes

DrawRect is the more efficient way i think. I'd like to extend jverrijt's nice answer. If you need alpha components (transparent to black gradient f.e.), then you can use this:

UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0.0);
CGContextSaveGState(UIGraphicsGetCurrentContext());
CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeClear);
CGContextRestoreGState(UIGraphicsGetCurrentContext());

//Draw stuffs

UIGraphicsEndImageContext();