How to Customize the Background/Border Colors of a Grouped Table View Cell

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

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
}

Changing border color in iPhone UITableView cells (non-grouped)

If by "border color" in a plain table view you mean the separator lines between the cells (default color gray), you can customize this color for the whole table view via:

tableView.separatorColor = [UIColor blueColor];

See the UITableView reference.

Create grouped UITableviewCell with custom selection Color and Border

I found a Solution to this. it is not totally the same (as UITableviewCell in grouped Style got a even more sophisticated Design in iOS5 but this is sufficient to me. I borrowed this Approach from
http://cocoawithlove.com/2010/12/uitableview-construction-drawing-and.html

and it works great!

The code I used is: http://www.mediafire.com/?mdxkpfe8g74ctk9

Hope this helps others

Change the color in between cells in grouped table view

I do believe the correct way to do this is setBackgroundColor for the tableview. you can do this in the viewDidLoad method so the color is already set when the view loads

Edit:

I would suggest make a custom subclass of UITableViewCell with the background color/image already included in the cell. Then you would have to also set the headers and footers to have the same background color/image. I believe this would be the easiest way to accomplish what you want

How to change a grouped UITableView cell's background to black (or non-white)?

I believe that the rounded corners of the Grouped style are actually backgrounds of the table cells. Thus you can't just replace the white part, because it's not solid color with drawn border - it's ImageView acting as backgroundView for the cell (using different graphics depending of the cell row and number of rows in section).

So either you try with your own graphics so you can keep the roundness (I'm trying something out for myself, not fully figured yet) or set each cell.backgroundView to nil and use cell.backgroundColor = [UIColor blackColor];

How to set selected background color on grouped UITableView

You can create 4 different images, 1 for top, 1 for bottom, 1 for middle, and 1 for top/bottom (rounded on all 4 corners). Then set the background view to your custom image, depending on the position in the table. Alternatively, if you want to use a view, here's a custom view that rounds only specific corners:

.h

#import <UIKit/UIKit.h>

enum {
RoundedCornerNone = 0,
RoundedCornerUpperRight = 1 << 0,
RoundedCornerLowerRight = 1 << 1,
RoundedCornerLowerLeft = 1 << 2,
RoundedCornerUpperLeft = 1 << 3
};
typedef NSUInteger RoundedCornerOptions;

@interface PartiallyRoundedView : UIView

@property (nonatomic, assign) RoundedCornerOptions roundedCorners;

@end

.m

#import "PartiallyRoundedView.h"


@implementation PartiallyRoundedView

@synthesize roundedCorners;

- (id)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame])) {
}
return self;
}

- (void)drawRect:(CGRect)rect
{
float radius = 10;

CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 1.0);
CGContextBeginPath(context);
CGContextSetRGBStrokeColor(context, .6, .6, .6, 1);
CGContextSetRGBFillColor(context, .968, .968, .968, 1);

CGContextMoveToPoint(context, rect.origin.x + rect.size.width - radius, rect.origin.y);
CGContextAddLineToPoint(context, rect.origin.x + radius, rect.origin.y); //Draw top line

if (self.roundedCorners >=8) { //Round upper-left corner
CGContextAddArc(context, rect.origin.x + radius, rect.origin.y + radius, radius,
-M_PI / 2, M_PI, 1);

self.roundedCorners-=8;
}
else {
CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y);
CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y + radius);
}

CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y + rect.size.height - radius); //Draw left line

if (self.roundedCorners >=4) { //Round lower-left corner
CGContextAddArc(context, rect.origin.x + radius , rect.origin.y + rect.size.height - radius,
radius, M_PI, M_PI / 2, 1);

self.roundedCorners-=4;
}
else {
CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y + rect.size.height);
CGContextAddLineToPoint(context, rect.origin.x + radius, rect.origin.y + rect.size.height);
}

CGContextAddLineToPoint(context, rect.origin.x + rect.size.width - radius, rect.origin.y + rect.size.height); //Draw bottom line

if (self.roundedCorners >=2) { //Round lower-right corner
CGContextAddArc(context, rect.origin.x + rect.size.width - radius ,
rect.origin.y + rect.size.height - radius, radius, M_PI / 2, 0.0f, 1);

self.roundedCorners-=2;
}
else {
CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);
CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y + rect.size.height - radius);
}

CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y + radius); //Draw right line

if (self.roundedCorners ==1) { //Round upper-right corner
CGContextAddArc(context, rect.origin.x + rect.size.width - radius, rect.origin.y + radius,
radius, 0.0f, -M_PI / 2, 1);
}
else {
CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y);
CGContextAddLineToPoint(context, rect.origin.x + rect.size.width - radius, rect.origin.y );
}


CGContextClosePath(context);
CGContextDrawPath(context, kCGPathFillStroke);
}


- (void)dealloc {
[super dealloc];
}


@end

You can create an instance of this view (you'll need to add a bit to fill the middle with whatever color you want). Just pass in the correct corner rounding depending on if you are the first, last, middle, or first and last cell.

Customize UITableView section border color for each section

I believe what Apple uses for its contact heading is tableView:viewForHeaderInSection: for section 0, instead of a cell in the first section. You can still specify a transparent background and the pinstripe will show behind it. The border will not be there as grouped table view section headers do not have borders.

Whether you built your custom cell in Interface Builder or using code, it should be a fairly trivial task to migrate those views from a UITableViewCell to a UIView for use with tableView:viewForHeaderInSection:.

I don't know if you'll be able to keep the Details title for, say, section 1, unless you make a label containing that word and add it to the section 0 header view manually.



Related Topics



Leave a reply



Submit