views:

21778

answers:

5

My application needs to display text in either a View or Label but the back ground must be a gradient as opposed to a true color. Using a graphics program to create desired look is no good as the text may vary depending on data returned from a server.

Does anyone know the quickest way to tackle this? Your thoughts are greatly appreciated.

+22  A: 

You can use Core Graphics to draw the gradient, as pointed to in Mike's response. As a more detailed example, you could create a UIView subclass to use as a background for your UILabel. In that UIView subclass, override the drawRect: method and insert code similar to the following:

- (void)drawRect:(CGRect)rect 
{
    CGContextRef currentContext = UIGraphicsGetCurrentContext();

    CGGradientRef glossGradient;
    CGColorSpaceRef rgbColorspace;
    size_t num_locations = 2;
    CGFloat locations[2] = { 0.0, 1.0 };
    CGFloat components[8] = { 1.0, 1.0, 1.0, 0.35,  // Start color
         1.0, 1.0, 1.0, 0.06 }; // End color

    rgbColorspace = CGColorSpaceCreateDeviceRGB();
    glossGradient = CGGradientCreateWithColorComponents(rgbColorspace, components, locations, num_locations);

    CGRect currentBounds = self.bounds;
    CGPoint topCenter = CGPointMake(CGRectGetMidX(currentBounds), 0.0f);
    CGPoint midCenter = CGPointMake(CGRectGetMidX(currentBounds), CGRectGetMidY(currentBounds));
    CGContextDrawLinearGradient(currentContext, glossGradient, topCenter, midCenter, 0);

    CGGradientRelease(glossGradient);
    CGColorSpaceRelease(rgbColorspace); 
}

This particular example creates a white, glossy-style gradient that is drawn from the top of the UIView to its vertical center. You can set the UIView's backgroundColor to whatever you like and this gloss will be drawn on top of that color. You can also draw a radial gradient using the CGContextDrawRadialGradient function.

You just need to size this UIView appropriately and add your UILabel as a subview of it to get the effect you desire.

EDIT (4/23/2009): Per St3fan's suggestion, I have replaced the view's frame with its bounds in the code. This corrects for the case when the view's origin is not (0,0).

Brad Larson
I tried this code but it is not correct. Instead of setting currentFrame to self.frame it should be set to self.bounds.
St3fan
You're right, thanks for pointing it out. I had since corrected my own code, but forgot that this needed updating. The case that gets you is when the origin of the view has a different Y position than 0. The gradient then gets drawn offset from the vertical center.
Brad Larson
Can be this applied to UIImage or UIImageView to have any image with gradient?
sashaeve
You can place this over a UIImageView to add a gradient. For altering the contents of an image, you might need to draw the image first to a context, draw the gradient above it in that context, and then save the context as a new image.
Brad Larson
+8  A: 

You could also use a graphic image one pixel wide as the gradient, and set the view property to expand the graphic to fill the view (assuming you are thinking of a simple linear gradient and not some kind of radial graphic).

Kendall Helmstetter Gelner
Hey Kendall,thanks man you triggered a duh switch for me. Solved it simply by placing a gradient into the UIImageView and place the dynamic label on top of that. Thanks to all for your help.Tony
TonyNeallon
A: 

I achieve this in a view with a subview that is an UIImageView. The image the ImageView is pointing to is a gradient. Then I set a background color in the UIView, and I have a colored gradient view. Next I use the view as I need to and everything I draw will be under this gradient view. By adding a second view on top of the ImageView, you can have some options whether your drawing will be below or above the gradient...

mahboudz
+78  A: 

I realize this is an older thread, but for future reference:

As of iPhone SDK 3.0, custom gradients can be implemented very easily, without subclassing or images, by using the new CAGradientLayer:

 UIView *view = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 100)] autorelease];
 CAGradientLayer *gradient = [CAGradientLayer layer];
 gradient.frame = view.bounds;
 gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor blackColor] CGColor], (id)[[UIColor whiteColor] CGColor], nil];
 [view.layer insertSublayer:gradient atIndex:0];

Take a look at the CAGradientLayer docs. You can optionally specify start and end points (in case you don't want a linear gradient that goes straight from the top to the bottom), or even specific locations that map to each of the colors.

Mirko Froehlich
Just in case my comment catches anyone's eye as they consider implementing the other solutions above, DO THIS ONE. It couldn't be easier (but do remember that you'll need to add the QuartzCore framework and import `#import <QuartzCore/QuartzCore.h>` in your class).
Justin Searls
Great work: much easier that the other solutions out there.
jkp
I like this but I'm wondering how the performance of this compares to pre-rendering an image with the gradient. I'm particularly thinking about the case of table view cells, where during scrolling there could be lots of redrawing.
cantabilesoftware
Good point. I only used this as a fixed background for the entire view, and didn't notice any significant overhead. Not sure how well it performs on individual table cells. Should be easy to find out, though.
Mirko Froehlich
Someone may apply additional effect e.g., cornerRadius. They must add more code here: `view.layer.masksToBounds = YES;` to make sure thing goes smooth.
iwat
This worked perfectly, thanks so much!
jboxer
What way provides the best performance? Using CAGradientLayer or UIImageViews?
Sam V