« Back to blog

How to Make Custom Drawn Gradient Backgrounds in a Grouped UITableView with Core Graphics

In iPhone app design, it is important to find a balance between customization and familiarity.  Many times, subtle differences are all you need to make yourself stand out from the crowd.  While doing the Ambiance 3.0 redesign, I wanted something to make my list of content a little different than all the other cookie cutter table views out there.

A great place to start is to implement your own background and use a clear table view background.  Many apps are now doing this and it is come to be expected from a grouped UITableView that is done with a little love.  Another way to spruce up these tables is to add a custom background color.  Since 3.0, this has been as easy as setting the cells backgroundColor property.  I implemented both of these and it wasn't enough for me. It still looked like so many apps out there.  I thought about putting a gradient view as the background, only to find that setting a grouped UITableViewCell's background ignored the nice rounded corners of the cell.  Almost giving up, I googled around to see if anybody else has done it and shared some code.

This was a great resource as it helped me in the right direction — Core Graphics.  It was meant as a way to customize the background of a cell before the 3.0 sdk came out, but I used it as a basis for my code to draw a gradient!  It needed tweaking and optimization, but after a little bit of hacking away at it, I was able to get it to work nicely.  I present to you the UACellBackgroundView.

064173b21fcbf937101ccfdac7d80b71

To use the UACellBackgroundView, simply add the .h and .m files to your project, then use it as the cell background view.

.h file
.m file

Whenever you want to use it, just set the cell's backgroundView to be the UACellBackgroundView in your own UITableViewCell Subclass's initWithStyle  method.  Then, when you have your data and are creating cells, simply set the position of the cell by calling setPosition, of just call the line directly if you don't want to subclass the UITableViewCell.  The position is important as it lets the cell know to draw itself correctly depending on whether or not the cell is first, last, in the middle, or a single cell.

Hope this helps you in your quest for a better app.  If you want to use it, you will have to set your cell labels and elements to have a clear background, so hopefully you have a fast drawing method and have optimized your table view cells to do minimum work during scrolling.

| Viewed
times | Favorited 0 times

8 Comments

Sep 29, 2010
Shukuyen said...
Many thanks for this! Now I just have to find a way to make the group header views equally good looking :)
Oct 01, 2010
Shukuyen said...
Me again ;-) I have one problem with UABackgroundCellView, maybe you already have a solution for this.

In cellForRowAtIndexPath I set the position of each row. When a row is moved by the user (moveRowAtIndexPath) the position property of the UABackgroundCellView should be adjusted accordingly. How to do this?

Thanks,
Shukuyen.

Oct 01, 2010
Matt Coneybeare said...
I have code that calls setPosition on the visible cells after each moved row.
Oct 01, 2010
Shukuyen said...
Thanks for your answer.

If any other noob is wondering how this could work, here is how I did it (be aware that this code might not be a good solution ;)):

In your UITableViewDataSource do the following:

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
// Change background according to new position
NSArray *staticCells = [tableView visibleCells];
NSMutableArray *cells = [NSMutableArray arrayWithArray:staticCells];
[cells moveObjectFromIndex:fromIndexPath.row toIndex:toIndexPath.row];

for (int i = 0; i < [cells count]; ++i) {
UITableViewCell *cell = [cells objectAtIndex:i];
if ([cells count] == 1) {
[(UACellBackgroundView *)cell.backgroundView setPosition:UACellBackgroundViewPositionSingle];
} else {
if (i == 0) {
[(UACellBackgroundView *)cell.backgroundView setPosition:UACellBackgroundViewPositionTop];
} else if (i == [cells count] - 1) {
[(UACellBackgroundView *)cell.backgroundView setPosition:UACellBackgroundViewPositionBottom];
} else {
[(UACellBackgroundView *)cell.backgroundView setPosition:UACellBackgroundViewPositionMiddle];
}
}
}

// Modify you datasource here
}

Nov 09, 2010
woot said...
You're my f*ckin god
Oct 04, 2011
I'm trying to add a background image to a cell, but if i create a UIImageView and set backgroundView of cell with this new view I lose rounded corners. If I use "addSubView" image doesn't appear at all. Does anybody know how to add a background image to a UITableViewCell?

Thanx

Oct 19, 2011
mathew_waters said...
This is great, and thank you for sharing with everyone.

I found a link to this on Stackoverflow but since then I've found a very simple way to add a gradient to the grouped style cells, which only involves one image for the gradient. See my answer on...

http://stackoverflow.com/questions/1979165/applying-background-gradient-to-a-...

Thanks again!
Mathew

Oct 20, 2011
Matt Coneybeare said...
The whole point of this post is to custom draw the cells so that no images are necessary. This is the bet option as you can support any height of cell, and dynamically alter the appearance of the cells without including tons of images.

Leave a comment...