35

I've been looking for ways to improve the overall attractiveness of my iPhone applications. A majority of the functionality happens in UITableView. I think I can start by adding subtle gradients to UITableViewCells, as that seems to improve the feel of the app by an order of magnitude. Selecting the appropriate fonts/sizes helps a great deal also. My question for this forum is, what's the best strategy of adding gradients to UITableViewCells? Are you using Core Graphics/Quartz? Are you using a 1x1 pixel image and stretching it? I'm interesting in something along the lines of the following screenshot of the Tumblr iPhone app: http://dl-client.getdropbox.com/u/57676/screenshots/tumblr.jpg

Does anyone have any good examples of how to make your UITableViewCell's stick out?

And for performance reasons is it better to use an image or draw with Quartz? If Quartz, I'd love to see some sample codes of how folks are drawing the gradients into the cells.

Thanks.

  • 4
    The Tumblr iPhone app looks awful --both the gradients and the unnecessary boxed look imposed by the gray border. Stick to the standard UITableView look. What Apple uses for *their* apps is what looks most professional, not random novelty stuff. – Hejazzman Apr 21 '09 at 02:46
  • @foljs -- while I agree Tumblr's gradients don't look great, it's a good question and there are examples of gradient table cells that look fine (e.g. Tweetie if you turn off the chat bubbles look). Apple uses custom cell backgrounds in the App Store app, too (though not a gradient). – Daniel Dickison Apr 22 '09 at 16:01

7 Answers7

62

I work for Tumblr, and while I didn't write the iPhone app (he did), I have the source and can tell you how it's done.

In -tableView:cellForRowAtIndexPath:

cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"postCellBackground.png"]];
cell.selectedBackgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"postCellBackgroundSelected.png"]];

Pretty simple, really: PNG images in a UIImageView as the cell's background views.

The two images are 1x61 vertical gradients that UIKit automatically stretches horizontally to fit the width of the cell.

Marco
  • 14,977
  • 7
  • 36
  • 33
  • This is creating a new instance of the Image for each cell. It works but could not be so memory efficient. Is there a way to have only a reference imageview and assign it to each backgroundView as a reference pointing to that image? – Rigo Vides Jul 05 '11 at 22:17
  • 3
    Correct me if I'm wrong, but, `UIImage` I think has its own internal cache where it doesn't have to create new instances of images each time someone requests it to fetch an image? – Tejaswi Yerukalapudi Jul 25 '11 at 04:57
  • 1
    don't forget this line: [[cell textLabel] setBackgroundColor:[UIColor clearColor]]; – Rafael Sanches Aug 24 '11 at 06:09
31

As of iPhone SDK 3.0, there's a much simpler solution that relies on the new CAGradientLayer and doesn't require subclassing or images.

Community
  • 1
  • 1
Mirko Froehlich
  • 12,006
  • 4
  • 27
  • 23
2

Marco's answer works great for plain table view cells and for grouped table view cells that are located in the middle of the table view, but if you try to set a background view for the first/last cell in a grouped table then it will break the rounded corners. To fix it you can set cell background color to a UIColor colorWithPatternImage, e.g:

cell.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"Gradient.png"]]; 
Dmitry Sokurenko
  • 6,042
  • 4
  • 32
  • 53
0

I'd use Quartz 2D for this, but setting up images in Photoshop is perfectly valid too.

As for performance, if you're re-using cells by type I don't think it would be an issue - but if you do find it a bottleneck you could draw to a bitmap context once, obtain an image from that and use that everywhere - a sort of hybrid solution.

philsquared
  • 22,403
  • 12
  • 69
  • 98
  • Marco's answer seems to suggest that UIImageView does in fact stretch its image, perhaps because its frame/bounds get set explicitly by the cell layout? – Daniel Dickison Apr 22 '09 at 16:04
  • yeah, as I said that's perfectly valid. It's just that if you know Quartz 2D it's so easy to do this that that would be my first course, personally – philsquared Apr 22 '09 at 18:54
  • I just noticed that my comment above doesn't make any sense -- I think I had meant to comment on HitScan's answer instead of yours. Sorry for the confusion! – Daniel Dickison Apr 24 '09 at 01:41
0

UITableViewCell supports separate views for their background and selected background, so it makes sense to make use of these properties. To do that, you're going to need to come up with an image that's the full size of your cell anyway (UIImageView doesn't stretch it's image), so you may as well make it on a desktop machine once, and save the cycles on the phone that would have to be spent to stretch an image or make it dynamically. Though if you intend to allow the user to change the gradient colors, you'll have to create it once dynamically anyway.

HitScan
  • 8,651
  • 3
  • 22
  • 17
0

I think the easiest way, by far, of handling UITableView with custom cell is using Interface Builder. It makes UI design work much easier than doing it by pure core. Here is a great tutorial (with a video!) on how to do that. Highly recommended. I am not using any other method of UITableView coding since I followed that.

Having said so, adding a gradient to your cell will be extremely easy. Just use InterfaceBuilder to add an image containing your gradient to the cell view and you are done. You won't have to worry about Quartz, and performance wise you'll get similar results since CocoaTouch's components are very well optimized to do plain task such as displaying an image.

Pablo Santa Cruz
  • 176,835
  • 32
  • 241
  • 292
0

Mirko's answer is a good alternative if you don't want to use an image. However it's best to add the gradient to the backgroundView rather the UITableViewcell itself. This way you won't lose the highlight effects when selecting the cell

Community
  • 1
  • 1
wL_
  • 997
  • 8
  • 13