Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIView backgroundColor disappears when UITableViewCell is selected

I have a simple tableViewCell build in interface builder. It contains a UIView which contains an image. Now, when I select the cell, the default blue selection background is shown, but the backgroundColor of my UIView is gone.

My UITableViewCell's implementation file doesn't do anything special. It just init's & returns self and all I do in setSelected is call super.

How do I get my UIView backgroundColor to show when the tableView is selected?

like image 999
Tycho Pandelaar Avatar asked Mar 07 '11 17:03

Tycho Pandelaar


4 Answers

The problem here is that the [super] implementation of

- (void) setSelected:(BOOL) selected animated:(BOOL) animated;

sets all the background colors in the UITableViewCell to rgba(0,0,0,0). Why? Perhaps to make us all sweat?

It is not that entire views disappear (as evidenced by the fact that if you change the views layer border properties, those are retained)

Here is the sequence of function calls that results from touching a cell

  1. setHighlighted
  2. touchesEnded
  3. layoutSubviews
  4. willSelectRowAtIndexPath (delegate side)
  5. setSelected (!!! this is where all your view background colors are told to disappear)
  6. didSelectRowAtIndexPath (delegate side)
  7. setSelected (again) (Interestingly background colors not cleared on this call. What strangeness is going on inside that super method?)
  8. layoutSubviews (again)

So your options are to

  1. Override - (void) setSelected:(BOOL) selected animated:(BOOL) animated; without calling [super setSelected:selected animated:animated]. This will give you the most technically correct implementation because a) the code is wrapped up inside the UITableViewCell subclass and b) because it is only called when needed (well twice when needed, but maybe there is a way around that). The down side is you'll have to re-implement all the necessary functions (as opposed to unnecessary color clearing functions) of setSelected. Now don't ask me how to properly override setSelected just yet. Your guess is as good as mine for now (be patient, I'll edit this answer once I figure it out).
  2. Re-assert the background colors in didSelectRowAtIndexPath. This is not so great because it puts what should be instance code outside the instance. It has the upside that it is only called when it is needed, as opposed to ...
  3. Re-assert the background colors in layoutSubviews. This is not great at all because layoutSubviews is called like A MILLION times! It is called every time the table refreshes, every time it scrolls, every time you grandmother gets a perm... like seriously, a million times. That means there is a lot of unnecessary background re-assertions and a lot of extra processing overhead. On the bright side it puts the code inside the UITableViewCell subclass, which is nice.

Unfortunately re-asserting the background colors in setHighlighted does nothing because setHighlighted is called before all the background colors get set to [r:0 b:0 g:0 a:0] by the first call to setSelected.

//TODO: Give a great description of how to override setSelected (stay tuned)

like image 141
Brooks Avatar answered Sep 19 '22 23:09

Brooks


- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated
{
    UIColor *backgroundColor = self.channelImageView.backgroundColor;
    [super setHighlighted:highlighted animated:animated];
    self.channelImageView.backgroundColor = backgroundColor;
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    UIColor *backgroundColor = self.channelImageView.backgroundColor;
    [super setSelected:selected animated:animated];
    self.channelImageView.backgroundColor = backgroundColor;
}
like image 23
Michal Zaborowski Avatar answered Sep 22 '22 23:09

Michal Zaborowski


When your UITableViewCell is selected, there are two states you should pay attention to: Highlighted and Selected.

So, for scenarios that you have a custom cell class which is subclass of UITableViewCell, you can easily override these two methods to avoid this situation(Swift):

class MyCell: UITableViewCell {

    @IBOutlet var myView: UIView!

    override func setHighlighted(highlighted: Bool, animated: Bool) {
        let myViewBackgroundColor = myView.backgroundColor
        super.setHighlighted(highlighted, animated: animated)
        myView.backgroundColor = myViewBackgroundColor
    }

    override func setSelected(selected: Bool, animated: Bool) {
        let myViewBackgroundColor = myView.backgroundColor
        super.setSelected(selected, animated: animated)
        myView.backgroundColor = myViewBackgroundColor
    }

}
like image 17
kubilay Avatar answered Sep 18 '22 23:09

kubilay


Previously I have done as @P5ycH0 said (1x1 image stretched), but following @Brooks I figured that overriding -(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated in my custom UITableViewCell implementation and resetting the the background colors after calling [super setHighlighted:highlighted animated:animated]; keeps my background colors when the cell is selected/highlighted

-(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated {
    [super setHighlighted:highlighted animated:animated];
    myView.backgroundColor = myColor;
}
like image 16
ZeCodea Avatar answered Sep 18 '22 23:09

ZeCodea