Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p><strong>UPDATE:</strong> In iPhone OS 3.0 and later <code>UITableViewCell</code> now has a <code>backgroundColor</code> property that makes this really easy (especially in combination with the <code>[UIColor colorWithPatternImage:]</code> initializer). But I'll leave the 2.0 version of the answer here for anyone that needs it…</p> <hr> <p>It's harder than it really should be. Here's how I did this when I had to do it:</p> <p>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.</p> <p>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.</p> <p>It's a real PITA but I've confirmed with Apple engineers that this is currently the only way.</p> <p><strong>Update</strong> 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:</p> <pre><code>// // CustomCellBackgroundView.h // // Created by Mike Akers on 11/21/08. // Copyright 2008 __MyCompanyName__. All rights reserved. // #import &lt;UIKit/UIKit.h&gt; 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 } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload