UIView: How to Make Shiny Backgrounds and Other Reusable Styles

Sphericle 3.0 screenshot demonstrating reusable styles

Note: If you find this post helpful, consider purchasing Shiny Styles: Documented Source Code, an XCode project with well-documented source code to make an app that demonstrates these techniques.

When I first started making iPhone apps, I wrote a lot of repetitive code to style interface elements. Certainly, getting comfortable with Interface Builder eases that pain to some degree, but IB won't allow you to take advantage of a lot of available built-in styling features for your interface elements, such as curved corners, drop shadows, and stroked borders. Additionally, you can create beautiful gradient backgrounds in code pretty easily, but the code is somewhat verbose, so it really pays off to find good ways of re-using that kind of code. Also, using a programmatic approach to your app styling can eliminate the production time associated with image-based styles (e.g. custom background images). A lot of common effects used in UIs can be realized without any images whatsoever.

Today, I want to show you a couple of methods that encapsulate code-based styling for your UIViews and their descendants. These methods can be used either in a subclass of UIView, or a Category on UIView. My recommendation is to go the Category route, so that you can use the methods on any UIView or subclass (e.g. UIImageView). However, if you end up creating styles that need their own instance variables, then you'll need to write a subclass. If you need more information what a Category is or how to create one, check the Apple documentation.

Curved Corners, Stroked Borders, and Drop Shadows

Here's a method to encapsulate some style settings that use the CALayer instance (the layer property) inside of a UIView. Let's say we have an app in which we repeatedly use the style of a UIView with 4-pixel-radius curved corners, a 1-pixel light gray border, and a mild drop shadow. We can write a method that applies those styles to a UIView (make sure you import QuartzCore so that this method will compile):

#import <QuartzCore/QuartzCore.h>

...

- (void)applyDefaultStyle {
    // curve the corners
    self.layer.cornerRadius = 4;

    // apply the border
    self.layer.borderWidth = 1.0;
    self.layer.borderColor = [[UIColor lightGrayColor] CGColor];

    // add the drop shadow
    self.layer.shadowColor = [[UIColor blackColor] CGColor];
    self.layer.shadowOffset = CGSizeMake(2.0, 2.0);
    self.layer.shadowOpacity = 0.25;
}

Doing this, we have a central place in our app that this style is defined. If, later in development/design iterations, we realize that all of those elements should have a dark gray border, we just have to make that change in one place.

Adding a Shiny Gradient Background

Next, let's create a method to apply a shiny-looking gradient to the background of any UIView. As a bonus, we'll set up the method such that any single color can be passed in, and the gradient will be drawn in that color. Note, the method I write here assumes that the color passed in is a UIColor in RGBA mode (not grayscale).

- (void)applyShinyBackgroundWithColor:(UIColor *)color {

    // create a CAGradientLayer to draw the gradient on
    CAGradientLayer *layer = [CAGradientLayer layer];

    // get the RGB components of the color
    const CGFloat *cs = CGColorGetComponents(color.CGColor);

    // create the colors for our gradient based on the color passed in
    layer.colors = [NSArray arrayWithObjects:
                                    (id)[color CGColor],
                                    (id)[[UIColor colorWithRed:0.98f*cs[0] 
                                                         green:0.98f*cs[1] 
                                                          blue:0.98f*cs[2] 
                                                         alpha:1] CGColor],
                                    (id)[[UIColor colorWithRed:0.95f*cs[0] 
                                                         green:0.95f*cs[1] 
                                                          blue:0.95f*cs[2] 
                                                         alpha:1] CGColor],
                                    (id)[[UIColor colorWithRed:0.93f*cs[0] 
                                                         green:0.93f*cs[1] 
                                                          blue:0.93f*cs[2] 
                                                         alpha:1] CGColor],
                                    nil];

    // create the color stops for our gradient
    layer.locations = [NSArray arrayWithObjects:
                        [NSNumber numberWithFloat:0.0f],
                        [NSNumber numberWithFloat:0.49f],
                        [NSNumber numberWithFloat:0.51f],
                        [NSNumber numberWithFloat:1.0f],
                        nil];

    layer.frame = self.bounds;
    [self.layer insertSublayer:layer atIndex:0];
}

This method creates a CAGradientLayer, draws our styled gradient onto it, and then inserts that layer into the UIView at the appropriate location.

Shiny Styles XCode project So, with these two methods alone, you can create a nice-looking, stylized UIView, without using any decorative images. If you have any questions on how some of this stuff works, let me know in the Comments. And if you found this post helpful, consider purchasing Shiny Styles: Documented Source Code, an XCode project with well-documented source code to make an app that demonstrates these techniques.

Comments

Damon Clinkscales's picture

just wanted to show my shiny face on your shiny post.

Coming to Houndstooth for Cafe Bedouins tonight? :)

Latorz

Chadwick Wood's picture

I think so... Always kinda hard to keep up the motivation past 7pm!

DanM's picture

layer.colors? layer.locations? Did you create a category for the CALayer that includes these properties?

Chadwick Wood's picture

DanM, good catch! The code should be creating an instance of CAGradientLayer, not CALayer. colors and locations are properties of CAGradientLayer. I'll correct the code.

umar's picture

Thanks

Nice code.

Can I create this type of effect on UIView check this link http://www.flickr.com/photos/24313234@N07/5323036634/

please any one help me

Chadwick Wood's picture

Umar, if you want a masked outline for a UIView, you'll need to write custom drawing code, I think. Same for adding a drop shadow to the masked shape. That effect is probably a situation where it would just be easier (and faster) to use a background image.

umar's picture

Thanks Chadwick Wood

I just started iPhone development and no idea how to do this.

I need it urgent. so please help me to write some piece of code.

I am very tankful to you. Thanks

Andrew Goodwin's picture

I know this is an older post but it is one of the top returns on google for "how to make a sniny uiview" so I figured I would offer a little bit of help. My colors weren't turning out correctly so I had to add "/255" after every "cs[i]" in the layer.colors NSArray. For example, the first object in the array reads "(id)[[UIColor colorWithRed:0.98*cs[0]/255 green: ... ] CGColor].

Just giving future visitors a heads up. Thanks for the informative post.

CC's picture

Thanks for the heads up. I was a little baffled why the code wasn't working. Your tip fixed that.