Reputation: 55534
I have a UIlabel on a UITableViewCell, which I've created programmatically (i.e. not a nib or a subclass).
When the cell is highlighted (goes blue) it makes all the background colors of the UILabels turn clear. I have 2 UILabels where I don't want this to be the case. Currently I'm using UIImageViews behind the UILabel's to make it look like the background color doesn't change. But this seems an inefficient way to do it.
How can i stop certain UILabel's background color changing when the UITableViewCell is highlighted?
Upvotes: 42
Views: 19443
Reputation: 2186
You need to subclass UITableViewCell and override the following two methods:
Objective-C:
- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated
{
UIColor *backgroundColor = self.myLabel.backgroundColor;
[super setHighlighted:highlighted animated:animated];
self.myLabel.backgroundColor = backgroundColor;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
UIColor *backgroundColor = self.myLabel.backgroundColor;
[super setSelected:selected animated:animated];
self.myLabel.backgroundColor = backgroundColor;
}
Swift
override func setSelected(_ selected: Bool, animated: Bool) {
let color = myLabel.backgroundColor
super.setSelected(selected, animated: animated)
myLabel.backgroundColor = color
}
override func setHighlighted(_ highlighted: Bool, animated: Bool) {
let color = myLabel.backgroundColor
super.setHighlighted(highlighted, animated: animated)
myLabel.backgroundColor = color
}
Upvotes: 55
Reputation: 21
Set background color to label.layer.backgroundColor can fix this.
It seems cell will change backgroundColor of UILabel when highlighting.
Upvotes: 2
Reputation: 151
I may be mistaken, but I couldn't find away to directly override an existing getter/setter in Swift. Building off user479821's answer, I found a workaround that seems to produce the desired results. I added the IBDesignable/IBInspectable annotations in case you use storyboard, which render's the final color in the editor.
@IBDesignable
class PersistentBackgroundLabel: UILabel {
@IBInspectable var persistentBackgroundColor: UIColor = UIColor.clearColor() {
didSet {
super.backgroundColor = persistentBackgroundColor
}
}
override var backgroundColor: UIColor? {
didSet {
if backgroundColor != persistentBackgroundColor {
backgroundColor = persistentBackgroundColor
}
}
}
}
Upvotes: 5
Reputation: 594
Another way to keep the background color from changing on highlight is to set the backgroundColor
property on the label's layer
instead of on the label itself.
#import <QuartzCore/QuartzCore.h>
...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Get a table cell
UITableViewCell *cell = [tableView dequeueReusableCellForIdentifier:@"cell"];
// Set up the table cell
cell.textLabel.text = @"This is a table cell.";
// If you're targeting iOS 6, set the label's background color to clear
// This must be done BEFORE changing the layer's backgroundColor
cell.textLabel.backgroundColor = [UIColor clearColor];
// Set layer background color
cell.textLabel.layer.backgroundColor = [UIColor blueColor].CGColor;
return cell;
}
The layer
is not affected by cell highlighting or selection.
Upvotes: 47
Reputation: 14298
I just create a flag in UILabel subclass to disable background color change after awakeFromNib or init. This allows the initial color set in storyboard to takes effect. And we don't have to call any extra methods.
@implementation MWPersistentBGLabel {
BOOL disableBackgroundColorChange;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self setup];
}
return self;
}
- (void)awakeFromNib {
[super awakeFromNib];
[self setup];
}
- (void)setup {
// disable background color change after setup is called
disableBackgroundColorChange = YES;
}
// if we ever have to change the color later on, we can do so with this method
- (void)setPersistentBackgroundColor:(UIColor*)color {
[super setBackgroundColor:color];
}
- (void)setBackgroundColor:(UIColor *)color {
if (!disableBackgroundColorChange) {
[super setBackgroundColor:color];
}
// do nothing - background color never changes
}
@end
Upvotes: 1
Reputation: 1
I couldn't get the accepted answer to work; not that I think the answer is incorrect (far from it - that appears to be the Right Way), but as I was writing my first iOS app my head was spinning with subclasses already. So I decided to cheat.
Let's say the custom cell was controlled by a TableViewCell
class. I created a single pixel .png
file of the correct background colour and created a UIImageView
object in my custom cell. I used the Attributes inspector to set the default image and used 'Scale To Fill'. For a little more visual appeal, I then added the following to the User Defined Runtime Attributes in the Identity inspector:
KeyPath Type Value
layer.cornerRadius Number 4
layer.masksToBounds Boolean YES
Voilá, rounded corners on the cheap.
Positioned directly behind the UILabel, it looks the business, though it obviously won't resize with content (as the only content is its own image). Not a problem for me as the data to be displayed had to be a fixed size anyway.
On some values it was good to have a different colour, which can be set really easily:
cell.deviceDetailBackground.image = [UIImage imageNamed:@"detailBackground2.png"];
Where 'cell' is the incarnation of my custom cell in the cellForRowAtIndexPath
method, created using TableViewCell *cell;
. No data to display?
cell.deviceDetailBackground.image = nil;
I'm sure there will be a good reason why this is a daft idea, but as I'm just starting out with iOS development this was an easy fix that worked for me. Feel free to tell me why not to do it!
Upvotes: -1
Reputation: 126
I got same problem and I guess it is sort of a UIKit framework bug. Thanks God I got a workaround: Order matters!!! Just follow the sequence:
- (void)tableView:(UITableView *)t willDisplayCell:(UITableViewCell*)c forRowAtIndexPath:(NSIndexPath *)i {
UIColor *bgc = [UIColor redColor];
// Set up the cell in following order:
c.textLabel.backgroundColor = bgc;
c.backgroundColor = bgc;
c.textLabel.text = @"foo";
}
I don't know why, but this sequence works fine and other order makes it appear as if c.textLabel.backgroundColor was forced to clearColor in some cells after deselecting them.
It was not a random behavior, it happened the first time the cells were reused, not when they were created, nor when they were secondly reused. With the workaround it works fine always.
Upvotes: 3
Reputation: 411
Alternatively subclass the label you don't want to change color:
@interface PersistentBackgroundLabel : UILabel {
}
- (void)setPersistentBackgroundColor:(UIColor*)color;
@end
@implementation PersistentBackgroundLabel
- (void)setPersistentBackgroundColor:(UIColor*)color {
super.backgroundColor = color;
}
- (void)setBackgroundColor:(UIColor *)color {
// do nothing - background color never changes
}
@end
Then set the color once explicitly using setPersistentBackgroundColor:. This will prevent background color changes from anywhere without using your custom explicit background color change method.
This has the advantage of also eliminating clear background in label during transitions.
Upvotes: 41
Reputation: 55534
I had to subclass the UItableView, create a list of tags of the view that I want to not make transparent background, and override the setHighlighted:animated: method so that it reset the specific labels background colour. longwinding and fidely, if only I had the source code t the UItableViewCell's actual class.
Upvotes: 0
Reputation: 9390
In my apps i had to change the uitableviewcell selection style blue color, so i had to set uiimage view, when i clicked the cell is highlighted as Imageview. And i removed the highlighted of the cell when i returned to the view. And i couldnt understand your problem clearly. So just given my code and Try this one,
cellForRowAtIndexPath Method:
CGRect a=CGRectMake(0, 0, 300, 100);
UIImageView *bImg=[[UIImageView alloc] initWithFrame:a];
bImg.image=[UIImage imageNamed:@"bg2.png"];
[bImg setContentMode:UIViewContentModeScaleToFill];
cell.selectedBackgroundView=bImg;
[bImg release];
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:YES];
NSIndexPath *deselect = [self.tableView indexPathForSelectedRow];
[self.tableView deselectRowAtIndexPath:deselect animated:NO];
}
Best Of Luck
Upvotes: 0