Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to customize the background/border colors of a grouped table view cell?

I would like to customize both the background and the border color of a grouped-style UITableView.

I was able to customize the background color by using the following:

tableView.contentView.backgroundColor = [UIColor greenColor]; 

But the border color is still something I don't know how to change.

How do I customize these two aspects of the grouped-style table view?

like image 293
jpm Avatar asked Dec 30 '08 17:12

jpm


1 Answers

UPDATE: In iPhone OS 3.0 and later UITableViewCell now has a backgroundColor property that makes this really easy (especially in combination with the [UIColor colorWithPatternImage:] initializer). But I'll leave the 2.0 version of the answer here for anyone that needs it…


It's harder than it really should be. Here's how I did this when I had to do it:

You need to set the UITableViewCell's backgroundView property to a custom UIView that draws the border and background itself in the appropriate colors. This view needs to be able to draw the borders in 4 different modes, rounded on the top for the first cell in a section, rounded on the bottom for the last cell in a section, no rounded corners for cells in the middle of a section, and rounded on all 4 corners for sections that contain one cell.

Unfortunately I couldn't figure out how to have this mode set automatically, so I had to set it in the UITableViewDataSource's -cellForRowAtIndexPath method.

It's a real PITA but I've confirmed with Apple engineers that this is currently the only way.

Update Here's the code for that custom bg view. There's a drawing bug that makes the rounded corners look a little funny, but we moved to a different design and scrapped the custom backgrounds before I had a chance to fix it. Still this will probably be very helpful for you:

// //  CustomCellBackgroundView.h // //  Created by Mike Akers on 11/21/08. //  Copyright 2008 __MyCompanyName__. All rights reserved. //  #import <UIKit/UIKit.h>  typedef enum  {     CustomCellBackgroundViewPositionTop,      CustomCellBackgroundViewPositionMiddle,      CustomCellBackgroundViewPositionBottom,     CustomCellBackgroundViewPositionSingle } CustomCellBackgroundViewPosition;  @interface CustomCellBackgroundView : UIView {     UIColor *borderColor;     UIColor *fillColor;     CustomCellBackgroundViewPosition position; }      @property(nonatomic, retain) UIColor *borderColor, *fillColor;     @property(nonatomic) CustomCellBackgroundViewPosition position; @end  // //  CustomCellBackgroundView.m // //  Created by Mike Akers on 11/21/08. //  Copyright 2008 __MyCompanyName__. All rights reserved. //  #import "CustomCellBackgroundView.h"  static void addRoundedRectToPath(CGContextRef context, CGRect rect,                                  float ovalWidth,float ovalHeight);  @implementation CustomCellBackgroundView @synthesize borderColor, fillColor, position;  - (BOOL) isOpaque {     return NO; }  - (id)initWithFrame:(CGRect)frame {     if (self = [super initWithFrame:frame]) {         // Initialization code     }     return self; }  - (void)drawRect:(CGRect)rect {     // Drawing code     CGContextRef c = UIGraphicsGetCurrentContext();     CGContextSetFillColorWithColor(c, [fillColor CGColor]);     CGContextSetStrokeColorWithColor(c, [borderColor CGColor]);      if (position == CustomCellBackgroundViewPositionTop) {         CGContextFillRect(c, CGRectMake(0.0f, rect.size.height - 10.0f, rect.size.width, 10.0f));         CGContextBeginPath(c);         CGContextMoveToPoint(c, 0.0f, rect.size.height - 10.0f);         CGContextAddLineToPoint(c, 0.0f, rect.size.height);         CGContextAddLineToPoint(c, rect.size.width, rect.size.height);         CGContextAddLineToPoint(c, rect.size.width, rect.size.height - 10.0f);         CGContextStrokePath(c);         CGContextClipToRect(c, CGRectMake(0.0f, 0.0f, rect.size.width, rect.size.height - 10.0f));     } else if (position == CustomCellBackgroundViewPositionBottom) {         CGContextFillRect(c, CGRectMake(0.0f, 0.0f, rect.size.width, 10.0f));         CGContextBeginPath(c);         CGContextMoveToPoint(c, 0.0f, 10.0f);         CGContextAddLineToPoint(c, 0.0f, 0.0f);         CGContextStrokePath(c);         CGContextBeginPath(c);         CGContextMoveToPoint(c, rect.size.width, 0.0f);         CGContextAddLineToPoint(c, rect.size.width, 10.0f);         CGContextStrokePath(c);         CGContextClipToRect(c, CGRectMake(0.0f, 10.0f, rect.size.width, rect.size.height));     } else if (position == CustomCellBackgroundViewPositionMiddle) {         CGContextFillRect(c, rect);         CGContextBeginPath(c);         CGContextMoveToPoint(c, 0.0f, 0.0f);         CGContextAddLineToPoint(c, 0.0f, rect.size.height);         CGContextAddLineToPoint(c, rect.size.width, rect.size.height);         CGContextAddLineToPoint(c, rect.size.width, 0.0f);         CGContextStrokePath(c);         return; // no need to bother drawing rounded corners, so we return     }      // At this point the clip rect is set to only draw the appropriate     // corners, so we fill and stroke a rounded rect taking the entire rect      CGContextBeginPath(c);     addRoundedRectToPath(c, rect, 10.0f, 10.0f);     CGContextFillPath(c);        CGContextSetLineWidth(c, 1);       CGContextBeginPath(c);     addRoundedRectToPath(c, rect, 10.0f, 10.0f);       CGContextStrokePath(c);  }   - (void)dealloc {     [borderColor release];     [fillColor release];     [super dealloc]; }   @end  static void addRoundedRectToPath(CGContextRef context, CGRect rect,                                 float ovalWidth,float ovalHeight)  {     float fw, fh;      if (ovalWidth == 0 || ovalHeight == 0) {// 1         CGContextAddRect(context, rect);         return;     }      CGContextSaveGState(context);// 2      CGContextTranslateCTM (context, CGRectGetMinX(rect),// 3                            CGRectGetMinY(rect));     CGContextScaleCTM (context, ovalWidth, ovalHeight);// 4     fw = CGRectGetWidth (rect) / ovalWidth;// 5     fh = CGRectGetHeight (rect) / ovalHeight;// 6      CGContextMoveToPoint(context, fw, fh/2); // 7     CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1);// 8     CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1);// 9     CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1);// 10     CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1); // 11     CGContextClosePath(context);// 12      CGContextRestoreGState(context);// 13 } 
like image 165
Mike Akers Avatar answered Sep 18 '22 07:09

Mike Akers