331
votes

I have created a custom UITableViewCell. The table view is showing data fine. What I am stuck in is when user touches cell of tableview, then I want to show the background color of the cell other than the default [blue color] values for highlighting the selection of cell. I use this code but nothing happens:

cell.selectedBackgroundView.backgroundColor=[UIColor blackColor];
30

30 Answers

379
votes

I think you were on the right track, but according to the class definition for selectedBackgroundView:

The default is nil for cells in plain-style tables (UITableViewStylePlain) and non-nil for section-group tables UITableViewStyleGrouped).

Therefore, if you're using a plain-style table, then you'll need to alloc-init a new UIView having your desired background colour and then assign it to selectedBackgroundView.

Alternatively, you could use:

cell.selectionStyle = UITableViewCellSelectionStyleGray;

if all you wanted was a gray background when the cell is selected. Hope this helps.

678
votes

No need for custom cells. If you only want to change the selected color of the cell, you can do this:

Objective-C:

UIView *bgColorView = [[UIView alloc] init];
bgColorView.backgroundColor = [UIColor redColor];
[cell setSelectedBackgroundView:bgColorView];

Swift:

let bgColorView = UIView()
bgColorView.backgroundColor = UIColor.red
cell.selectedBackgroundView = bgColorView
48
votes

Table View Cell selection background color can be set via the Storyboard in Interface Builder:

table view cell selection color None

37
votes

If you have a grouped table with just one cell per section, just add this extra line to the code: bgColorView.layer.cornerRadius = 10;

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

Don't forget to import QuartzCore.

30
votes

Swift 3: for me it worked when you put it in the cellForRowAtIndexPath: method

let view = UIView()
view.backgroundColor = UIColor.red
cell.selectedBackgroundView = view
22
votes

The following works for me in iOS 8.

I have to set the selection style to UITableViewCellSelectionStyleDefault for custom background color to work. If any other style, the custom background color will be ignored. There seems to be a change in behaviours as previous answers needs to set style to none instead.

The full code for the cell as follows:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"MyCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    // This is how you change the background color
    cell.selectionStyle = UITableViewCellSelectionStyleDefault;
    UIView *bgColorView = [[UIView alloc] init];
    bgColorView.backgroundColor = [UIColor redColor];
    [cell setSelectedBackgroundView:bgColorView];        
    return cell;
}
18
votes

Create a custom cell for your table cell and in the custom cell class.m put the code below, it will work fine. You need to place the desired color image in selectionBackground UIImage.

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    UIImage *selectionBackground = [UIImage imageNamed:@"yellow_bar.png"];
    UIImageView *iview=[[UIImageView alloc] initWithImage:selectionBackground];
    self.selectedBackgroundView=iview;
}
12
votes

Swift 3.0 extension

extension UITableViewCell {
    var selectionColor: UIColor {
        set {
            let view = UIView()
            view.backgroundColor = newValue
            self.selectedBackgroundView = view
        }
        get {
            return self.selectedBackgroundView?.backgroundColor ?? UIColor.clear
        }
    }
}

cell.selectionColor = UIColor.FormaCar.blue

9
votes
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    UIView *view = [[UIView alloc] init];
    [view setBackgroundColor:[UIColor redColor]];
    [cell setSelectedBackgroundView:view];
}

We need to set the selected background view in this method.

9
votes

In Swift 4, you can also set the background color of your table cell globally (taken from here):

let backgroundColorView = UIView()
backgroundColorView.backgroundColor = UIColor.red
UITableViewCell.appearance().selectedBackgroundView = backgroundColorView
8
votes

If you want to add a custom highlighted color to your cell (and your cell contains buttons,labels, images,etc..) I followed the next steps:

For example if you want a selected yellow color:

1) Create a view that fits all the cell with 20% opacity (with yellow color) called for example backgroundselectedView

2) In the cell controller write this:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
     self.backgroundselectedView.alpha=1;
    [super touchesBegan:touches withEvent:event];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    self.backgroundselectedView.alpha=0;
    [super touchesEnded:touches withEvent:event];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    self.backgroundSelectedImage.alpha=0;
    [super touchesCancelled:touches withEvent:event];
}
6
votes

If you are using a custom TableViewCell, you can also override awakeFromNib:

override func awakeFromNib() {
    super.awakeFromNib()

    // Set background color
    let view = UIView()
    view.backgroundColor = UIColor.redColor()
    selectedBackgroundView = view
}
5
votes

I want to note that the XIB editor offers you the following standard options:

Section: blue/gray/none

(the right-hand column with options, 4th tab, first group "Table View Cell", 4th subgroup, the 1st of 3 items reads "Selection")

Probably what you want to do may be achieved by selecting the right standard option.

5
votes

One more tip to Christian's way to show rounded corner background for grouped table.

If I use cornerRadius = 10 for cell, it shows four corner's rounded selection background. It's not the same with table view's default UI.

So, I think about easy way to resolve it with cornerRadius. As you can see from the below codes, check about cell's location (top, bottom, middle or topbottom) and add one more sub layers to hide top corner or bottom corner. This just shows exactly same look with default table view's selection background.

I tested this code with iPad splitterview. You can change patchLayer's frame position as you needed.

Please let me know if there is more easier way to achieve same result.

if (tableView.style == UITableViewStyleGrouped) 
{
    if (indexPath.row == 0) 
    {
        cellPosition = CellGroupPositionAtTop;
    }    
    else 
    {
        cellPosition = CellGroupPositionAtMiddle;
    }

    NSInteger numberOfRows = [tableView numberOfRowsInSection:indexPath.section];
    if (indexPath.row == numberOfRows - 1) 
    {
        if (cellPosition == CellGroupPositionAtTop) 
        {
            cellPosition = CellGroupPositionAtTopAndBottom;
        } 
        else 
        {
            cellPosition = CellGroupPositionAtBottom;
        }
    }

    if (cellPosition != CellGroupPositionAtMiddle) 
    {
        bgColorView.layer.cornerRadius = 10;
        CALayer *patchLayer;
        if (cellPosition == CellGroupPositionAtTop) 
        {
            patchLayer = [CALayer layer];
            patchLayer.frame = CGRectMake(0, 10, 302, 35);
            patchLayer.backgroundColor = YOUR_BACKGROUND_COLOR;
            [bgColorView.layer addSublayer:patchLayer];
        } 
        else if (cellPosition == CellGroupPositionAtBottom) 
        {
            patchLayer = [CALayer layer];
            patchLayer.frame = CGRectMake(0, 0, 302, 35);
            patchLayer.backgroundColor = YOUR_BACKGROUND_COLOR;
            [bgColorView.layer addSublayer:patchLayer];
        }
    }
}
4
votes

Swift 4+:

Add following lines in your table cell

let bgColorView = UIView()
bgColorView.backgroundColor =  .red
self.selectedBackgroundView = bgColorView

Finally it should be as below

override func setSelected(_ selected: Bool, animated: Bool)
    {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
        let bgColorView = UIView()
        bgColorView.backgroundColor =  .red
        self.selectedBackgroundView = bgColorView

    }
3
votes

As per custom color for a selected cell in UITableView, great solution as per Maciej Swic's answer

Just to add to that, you declare Swic's answer in the Cell configuration usually under:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

And for an added effect, instead of the system colors, you may use RGB values for a custom color look. In my code this is how I achieved it:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 

} 

 static NSString *CellIdentifier = @"YourCustomCellName";
 MakanTableCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

// Configure the cell...

if (cell == nil) {

cell = [[[NSBundle mainBundle]loadNibNamed:@"YourCustomCellClassName" owner:self options:nil]objectAtIndex:0];
                    } 

UIView *bgColorView = [[UIView alloc] init];
bgColorView.backgroundColor = [UIColor colorWithRed:255.0/256.0 green:239.0/256.0 blue:49.0/256.0 alpha:1];
bgColorView.layer.cornerRadius = 7;
bgColorView.layer.masksToBounds = YES;
[cell setSelectedBackgroundView:bgColorView];


return cell;

}

Let me know if that works for you as well. You can mess with the cornerRadius number for the effects on the corners of the selected cell.

3
votes

To add the background for all cells (using Maciej's answer):

for (int section = 0; section < [self.tableView numberOfSections]; section++) {
        for (int row = 0; row < [self.tableView numberOfRowsInSection:section]; row++) {
            NSIndexPath* cellPath = [NSIndexPath indexPathForRow:row inSection:section];
            UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:cellPath];

            //stuff to do with each cell
            UIView *bgColorView = [[UIView alloc] init];
            bgColorView.backgroundColor = [UIColor redColor];
            [cell setSelectedBackgroundView:bgColorView];
        }
    } 
2
votes

I've got a slightly different approach than everyone else that reflects the selection on touch rather than after being selected. I have a subclassed UITableViewCell. All you have to do is set the background color in the touch events, which simulates selection on touch, and then set the background color in the setSelected function. Setting the background color in the selSelected function allows for deselecting the cell. Make sure to pass the touch event to the super, otherwise the cell won't actually act as if its selected.

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
    self.backgroundColor = UIColor(white: 0.0, alpha: 0.1)
    super.touchesBegan(touches, withEvent: event)
}

override func touchesCancelled(touches: NSSet!, withEvent event: UIEvent!) {
    self.backgroundColor = UIColor.clearColor()
    super.touchesCancelled(touches, withEvent: event)
}

override func setSelected(selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    // Configure the view for the selected state
    self.backgroundColor = selected ? UIColor(white: 0.0, alpha: 0.1) : UIColor.clearColor()
}
2
votes

To override UITableViewCell's setSelected also works.

override func setSelected(selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    // Set background color
    let view = UIView()
    view.backgroundColor = UIColor.redColor()
    selectedBackgroundView = view
}
2
votes

for those that just want to get rid of the default selected grey background put this line of code in your cellForRowAtIndexPath func:

yourCell.selectionStyle = .None
2
votes

for Swift 3.0:

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let cell = super.tableView(tableView, cellForRowAt: indexPath)

    cell.contentView.backgroundColor = UIColor.red
}
2
votes

I use below approach and works fine for me,

class MyTableViewCell : UITableViewCell {

                var defaultStateColor:UIColor?
                var hitStateColor:UIColor?

                 override func awakeFromNib(){
                     super.awakeFromNib()
                     self.selectionStyle = .None
                 }

// if you are overriding init you should set selectionStyle = .None

                override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
                    if let hitColor = hitStateColor {
                        self.contentView.backgroundColor = hitColor
                    }
                }

                override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
                    if let defaultColor = defaultStateColor {
                        self.contentView.backgroundColor = defaultColor
                    }
                }

                override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
                    if let defaultColor = defaultStateColor {
                        self.contentView.backgroundColor = defaultColor
                    }
                }
            }
1
votes

Here is the important parts of the code needed for a grouped table. When any of the cells in a section are selected the first row changes color. Without initially setting the cellselectionstyle to none there is an annonying double reload when the user clicks row0 where the cell changes to bgColorView then fades and reloads bgColorView again. Good Luck and let me know if there is a simpler way to do this.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    if ([indexPath row] == 0) 
    {
        cell.selectionStyle = UITableViewCellSelectionStyleNone;

        UIView *bgColorView = [[UIView alloc] init];
        bgColorView.layer.cornerRadius = 7;
        bgColorView.layer.masksToBounds = YES;
        [bgColorView setBackgroundColor:[UIColor colorWithRed:.85 green:0 blue:0 alpha:1]];
        [cell setSelectedBackgroundView:bgColorView];

        UIColor *backColor = [UIColor colorWithRed:0 green:0 blue:1 alpha:1];
        cell.backgroundColor = backColor;
        UIColor *foreColor = [UIColor colorWithWhite:1 alpha:1];
        cell.textLabel.textColor = foreColor;

        cell.textLabel.text = @"row0";
    }
    else if ([indexPath row] == 1) 
    {
        cell.selectionStyle = UITableViewCellSelectionStyleNone;

        UIColor *backColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:1];
        cell.backgroundColor = backColor;
        UIColor *foreColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1];
        cell.textLabel.textColor = foreColor;

        cell.textLabel.text = @"row1";
    }
    else if ([indexPath row] == 2) 
    {
        cell.selectionStyle = UITableViewCellSelectionStyleNone;

        UIColor *backColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:1];
        cell.backgroundColor = backColor;
        UIColor *foreColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1];
        cell.textLabel.textColor = foreColor;

        cell.textLabel.text = @"row2";
    }
    return cell;
}

#pragma mark Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSIndexPath *path = [NSIndexPath indexPathForRow:0 inSection:[indexPath section]];
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:path];
    [cell setSelectionStyle:UITableViewCellSelectionStyleBlue];

    [tableView selectRowAtIndexPath:path animated:YES scrollPosition:UITableViewScrollPositionNone];

}

- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tvStat cellForRowAtIndexPath:indexPath];
    [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}

#pragma mark Table view Gestures

-(IBAction)singleTapFrom:(UIGestureRecognizer *)tapRecog
{

    CGPoint tapLoc = [tapRecog locationInView:tvStat];
    NSIndexPath *tapPath = [tvStat indexPathForRowAtPoint:tapLoc];

    NSIndexPath *seleRow = [tvStat indexPathForSelectedRow];
    if([seleRow section] != [tapPath section])
        [self tableView:tvStat didDeselectRowAtIndexPath:seleRow];
    else if (seleRow == nil )
        {}
    else if([seleRow section] == [tapPath section] || [seleRow length] != 0)
        return;

    if(!tapPath)
        [self.view endEditing:YES];

    [self tableView:tvStat didSelectRowAtIndexPath:tapPath];
}
1
votes
[cell setSelectionStyle:UITableViewCellSelectionStyleGray];

Make sure you have used the above line to use the selection effect

1
votes
override func setSelected(selected: Bool, animated: Bool) {
    // Configure the view for the selected state

    super.setSelected(selected, animated: animated)
    let selView = UIView()

    selView.backgroundColor = UIColor( red: 5/255, green: 159/255, blue:223/255, alpha: 1.0 )
    self.selectedBackgroundView = selView
}
1
votes

In case of custom cell class. Just override:

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state

    if (selected) {
        [self setBackgroundColor: CELL_SELECTED_BG_COLOR];
        [self.contentView setBackgroundColor: CELL_SELECTED_BG_COLOR];
    }else{
        [self setBackgroundColor: [UIColor clearColor]];
        [self.contentView setBackgroundColor: [UIColor clearColor]];
    }
}
0
votes

It's easy when the table view style is plain, but in group style, it's a little trouble, I solve it by:

CGFloat cellHeight = [self tableView:tableView heightForRowAtIndexPath:indexPath];
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kGroupTableViewCellWidth+2, cellHeight)];
view.backgroundColor = kCommonHighlightedColor;
cell.selectedBackgroundView = view;
[view release];
UIRectCorner cornerFlag = 0;
CGSize radii = CGSizeMake(0, 0);
NSInteger theLastRow = --> (yourDataSourceArray.count - 1);
if (indexPath.row == 0) {
    cornerFlag = UIRectCornerTopLeft | UIRectCornerTopRight;
    radii = CGSizeMake(10, 10);
} else if (indexPath.row == theLastRow) {
    cornerFlag = UIRectCornerBottomLeft | UIRectCornerBottomRight;
    radii = CGSizeMake(10, 10);
}
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:view.bounds byRoundingCorners:cornerFlag cornerRadii:radii];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = maskPath.CGPath;
view.layer.mask = shapeLayer;

noted the kGroupTableViewCellWidth, I define it as 300, it's the width of group table view cell width in iPhone

0
votes

I'm using iOS 9.3 and setting the color through the Storyboard or setting cell.selectionStyle didn't work for me, but the code below worked:

UIView *customColorView = [[UIView alloc] init];
customColorView.backgroundColor = [UIColor colorWithRed:55 / 255.0 
                                                  green:141 / 255.0 
                                                   blue:211 / 255.0 
                                                  alpha:1.0];
cell.selectedBackgroundView = customColorView;

return cell;

I found this solution here.

0
votes

Try Following code.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[cellIdArray objectAtIndex:indexPath.row] forIndexPath:indexPath];

    // Configure the cell...
    cell.backgroundView =
    [[UIImageView alloc] init] ;
    cell.selectedBackgroundView =[[UIImageView alloc] init];

    UIImage *rowBackground;
    UIImage *selectionBackground;


    rowBackground = [UIImage imageNamed:@"cellBackgroundDarkGrey.png"];
    selectionBackground = [UIImage imageNamed:@"selectedMenu.png"];

    ((UIImageView *)cell.backgroundView).image = rowBackground;
    ((UIImageView *)cell.selectedBackgroundView).image = selectionBackground;



    return cell;
}

//Swift Version:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {


        let cell = tableView.dequeueReusableCell(withIdentifier: "cell")! as UITableViewCell


        cell.selectedBackgroundView = UIImageView()
        cell.backgroundView=UIImageView()

        let selectedBackground : UIImageView = cell.selectedBackgroundView as! UIImageView
        selectedBackground.image = UIImage.init(named:"selected.png");

        let backGround : UIImageView = cell.backgroundView as! UIImageView
        backGround.image = UIImage.init(named:"defaultimage.png");

        return cell


    } 
0
votes

Swift 4.x

To Change the selection background Colour to anyColour use Swift Extension

Create UITableView Cell extension as below

extension UITableViewCell{

    func removeCellSelectionColour(){
        let clearView = UIView()
        clearView.backgroundColor = UIColor.clear
        UITableViewCell.appearance().selectedBackgroundView = clearView
    } 

}

Then call removeCellSelectionColour() with cell instance.