简体   繁体   中英

How to set selected background color on grouped UITableView

I've tried various approaches with no success. Its grouped UITableView. Want to change the background color of the selected cell.

I've tried creating a view, setting the background color and setting it to cell.selectedBackgroundView. It works to change the color, but the rounded corners of a section are lost.

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.

If you'd like to implement this feature with Core Graphics (without using images), give this a shot. My approach takes the same concept as your selected answer, yet uses a simple if/else (or switch:case depending on your data source size) to draw the correct background view for your grouped UITableViewCell. The following code only need to be included in your implementation file:

.m

UIView *bgColorView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width-24, 69)];
    bgColorView.backgroundColor = [UIColor magentaColor];
    UIBezierPath *maskPath;
    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    maskLayer.frame = bgColorView.bounds;

    if (row == 0) {
      maskPath = [UIBezierPath bezierPathWithRoundedRect:bgColorView.bounds
                                       byRoundingCorners:(UIRectCornerTopLeft | UIRectCornerTopRight)
                                             cornerRadii:CGSizeMake(8.0, 8.0)];
      maskLayer.frame = CGRectOffset(bgColorView.bounds, 1, 0);
      if ([self.tableView numberOfRowsInSection:1] == 1) {
        maskPath = [UIBezierPath bezierPathWithRoundedRect:bgColorView.bounds
                                         byRoundingCorners:(UIRectCornerAllCorners)
                                               cornerRadii:CGSizeMake(8.0, 8.0)];
      }
    } else if (row >= [self.tableView numberOfRowsInSection:1]-1) {
      maskPath = [UIBezierPath bezierPathWithRoundedRect:bgColorView.bounds
                                       byRoundingCorners:(UIRectCornerBottomLeft | UIRectCornerBottomRight)
                                             cornerRadii:CGSizeMake(8.0, 8.0)];
      maskLayer.frame = CGRectOffset(bgColorView.bounds, 1, 0);
    } else {
      maskPath = [UIBezierPath bezierPathWithRoundedRect:bgColorView.bounds
                                       byRoundingCorners:nil
                                             cornerRadii:CGSizeMake(0.0, 0.0)];
    }

    maskLayer.path = maskPath.CGPath;

    bgColorView.layer.mask = maskLayer;
    cell.selectedBackgroundView = bgColorView;

If you've utilized reuseable cells, the drawing should only occur once for each type.

Hope this helps someone who stumbles onto this thread... Cheers!

If you just want to change the selection color, look at this suggestion: UITableView Cell selected Color? Post this in the CellForRowAtIndexPath-Method:

UIView *bgColorView = [[UIView alloc] init];
[bgColorView setBackgroundColor:[UIColor redColor]];
bgColorView.layer.cornerRadius = 10; 
[cell setSelectedBackgroundView:bgColorView];
[bgColorView release];  

and don't forget to import QuartzCore. Works for me (iOS 5)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM