I've got a UILabel with a background color in a cell. When I select this cell, the cell changes the color (which it should) but it also changes the background of the label. I want the preserve the background color on the UILabel. When I use an image with just a random color in it it is preserved, but isn't there any better way?
Thanks in advance
Code:
_label = [UILabel new];
_label.translatesAutoresizingMaskIntoConstraints = NO;
_label.font = [UIFont systemFontOfSize:10.f];
_label.backgroundColor = HEXCOLOR(0xFFE5E5E5); //Macro just a UIColor
But I use this way to add a different selection color (could have something to do with it)
UIView *selectionColor = [[UIView alloc] init];
selectionColor.backgroundColor = HEXCOLOR(0XFFF1F1F1);
self.selectedBackgroundView = selectionColor;
self.contentView.backgroundColor = [UIColor whiteColor];
Nothing really more to it. Just a simple label added with autolayout to fill with a padding of 5.
Solution:
Create a subclass of UILabel and just not call super
- (instancetype) initWithColor:(UIColor *)color
{
self = [super init];
if (self) {
[super setBackgroundColor:color];
}
return self;
}
- (void) setBackgroundColor:(UIColor *)backgroundColor
{
//do nothing here!
}
The default behavior of UITableView is that when a cell is selected the background color of all the cell's subviews is temporarily removed.
We usually handled this issue by subclassing UILabel, overwrite setBackgroundColor: and simply do not call [super setBackgroundColor:] after we've set our own color.
#interface MyLabel : UILabel
#property(nonatomic) BOOL backgroundColorLocked;
#end
#implementation MyLabel
-(void) setBackgroundColor:(UIColor*)backgroundColor {
if (_backgroundColorLocked) {
return;
}
super.backgroundColor = backgroundColor;
}
#end
Usage:
MyLabel* label = …;
label.backgroundColor = UIColor.redColor;
label.backgroundColorLocked = YES;
As long as backgroundColorLocked is YES no-one, not even UITableView(Cell), can change the label's background color.
Related
I have created a custom UILabel class and set the default background color.
Here are .h and .m files of my custom class.
#import <UIKit/UIKit.h>
#interface imLabel : UILabel
#end
AND
#import "imLabel.h"
#implementation imLabel
- (void)drawRect:(CGRect)rect {
}
- (void) layoutSubviews {
self.backgroundColor = [UIColor redColor];
}
#end
It works fine, but here is what I need: I want this work only if the backgroundColor is not set in ViewController.
Here is my viewDidLoad
- (void)viewDidLoad {
[super viewDidLoad];
label = [[imLabel alloc] initWithFrame:CGRectMake(50, 50, 300, 300)];
label.backgroundColor = [UIColor blueColor];
[self.view addSubview:label];
}
You control whether set label's backgroundColor or not in ViewController, so the best way to meet your need that I think is check the label had set backgroundColor or not, if not then set it.
/* Somewhere in your ViewController */
if (!self.label.backgroundColor) {
self.label.backgroundColor = [UIColor redColor];
}
Delete all your other code in imLabel.m, then:-
(instancetype)initWithFrame:(CGRect)aRect { self = [super initWithFrame:aRect]; if (self) { self.backgroundColor = [UIColor redColor]; } return self;}
Thanks to #Meiliang Dong
I've created a custom sub-class GTLabel of UILabel to have the right font, size, color, etc...
When I create a GTLabel programmatically, everything works fine. When I create a UILabel in the IB, I just have to change its class into GTLabel and it works.
Now when I have a UIButton, with a titleLabel, I would like to transform this UILabel into a GTLabel.
I've created a class method in GTLabel :
+ (GTLabel*)labelFromLabel:(UILabel*)label
{
...
return myGTLabel;
}
I don't really see how I'm suppose to proceed in this method.
Am I suppose to do as bellow?
GTLabel *myGTLabel = [[GTLabel alloc] init];
// Get all the properties of the original label
myGTLabel.text = label.text;
myGTLabel.frame = label.frame;
// Do the modifications
myGTLabel.font = [UIFont fontWithName:#"Gotham-Light"
size:label.font.pointSize];
The idea would be to do something like
myButton.titleLabel = [GTLabel labelFromLabel:myButton.titleLabel];
Thanks for your help !
You could implement your custom UIButton ( eg. GTButton ) and redefine titleLabel property, setting the same propertylabel used for your GTLabel
something like:
#import "GTButton.h"
#implementation GTButton
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
-(UILabel *)titleLabel
{
UILabel* parentLabel = [super titleLabel];
parentLabel.font = [UIFont fontWithName:#"Gotham-Light"
size:parentLabel.font.pointSize];
// ... set all your attributes
return parentLabel;
}
#end
titleLabel method of UIButton is read-only.
Although this property is read-only, its own properties are read/write. Use these properties primarily to configure the text of the button.
For example:
UIButton *button = [UIButton buttonWithType: UIButtonTypeSystem];
button.titleLabel.font = [UIFont systemFontOfSize: 12];
button.titleLabel.lineBreakMode = UILineBreakModeTailTruncation;
Create custom class for UIButton as you create for label and set property in it.
I overrode (is that a real word? regardless) my UITableView headers with a common used UIView to be used across the app.
Its no biggie, just a back solid background, pre-selected font, font size, font weight, font color, etc. Thats REALLY all there is too it. In fact heres the UIView
TableSectionView.h
#import <UIKit/UIKit.h>
#interface TableSectionView : UIView {
NSString *textLabel;
UIColor *textColor;
UIColor *backgroundColor;
BOOL bold;
NSString *textFont;
NSInteger textSize;
}
#property (nonatomic, retain) NSString *textLabel, *textFont;
#property (nonatomic, retain) UIColor *textColor, *backgroundColor;
#property (nonatomic) BOOL bold;
#property (nonatomic) NSInteger textSize;
- (id)initWithFrame:(CGRect)frame andText:(NSString*)text;
#end
TableSectionView.m
#import "TableSectionView.h"
#implementation TableSectionView
#synthesize textLabel, backgroundColor, textColor, bold, textFont, textSize;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
-(id)initWithFrame:(CGRect)frame andText:(NSString *)text {
self = [self initWithFrame:frame];
if(self) {
textLabel = text;
textFont = #"Arial-BoldMT";
textSize = 16;
textColor = [[UIColor alloc] initWithRed:1 green:1 blue:1 alpha:1];
backgroundColor = [[UIColor alloc] initWithRed:0 green:0 blue:0 alpha:0.8];
}
return self;
}
-(void)layoutSubviews {
[super layoutSubviews];
UILabel *title = [[UILabel alloc] initWithFrame:self.frame];
title.text = [NSString stringWithFormat:#" %#", textLabel];
title.font = [UIFont fontWithName:textFont size:textSize];
title.textColor = textColor;
title.backgroundColor = backgroundColor;
[self addSubview:title];
}
#end
and how i use it in a file:
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
return [[TableSectionView alloc] initWithFrame:CGRectZero andText:#"Table Section Title"];
}
Nothing strange or unique here.
And this works, theres no problem with it showing up just fine. What happens is when you scroll the table view.
When you scroll up, the section header shifts down and stays there. The harder the velocity, the more the section header shifts down and stays there until you go back down to the top of the table.
This app has about 25 separate table views this header is to be apart of, and I really want to squash this rendering bug asap.
I wanted to post a screenshot, but due to a strict NDA, I am not allowed to without running risk of being fired.
But here is SOMETHING to visualize the problem. Ive blurred out all of the text, sorry I had no other choice :\
The black bar is the section header, the top of the image is the top of the UITableView. Notice how much that section header is DOWN, vs where it is supposed to be? (the top, like normal section headers). Im just not sure what to do here
I think your problem is here:
-(void)layoutSubviews {
[super layoutSubviews];
UILabel *title = [[UILabel alloc] initWithFrame:self.frame];
title.text = [NSString stringWithFormat:#" %#", textLabel];
title.font = [UIFont fontWithName:textFont size:textSize];
title.textColor = textColor;
title.backgroundColor = backgroundColor;
[self addSubview:title];
}
Adding subviews in layoutSubviews is odd. Why don't you do it in the initWithFrame to avoid confusing the rendering code of Cocoa?
EDIT: That also saves you from saving all those member vars, declaring all those properties & synthesizing them :)
EDIT 2: When you init the UILabel you should use as reference self.bounds instead of self.frame, too.
Suppose I create TTTableStyledTextItem objects in <TTTableViewDataSource> conforming class as follows:
NSString* text = [NSString stringWithFormat:#"<b>%#</b>\n%#", #"aaaa..", #"bbbb.."];
TTStyledText* styledText = [TTStyledText textFromXHTML:text lineBreaks:YES URLs:NO];
TTTableStyledTextItem* item = [TTTableStyledTextItem itemWithText:styledText URL:#"my://url"];
By default, the table view cell class returned by tableView:cellClassForObject: is going to be TTStyledTextTableItemCell.
This works all right by I'd like to customize the background color of the cell when it is in the normal state (when it is not in the selected state).
I've managed to change the cell's background in the selected state by creating a TTStyledTextTableItemCell subclass and overriding the initWithStyle:reuseIdentifier: initializer as follows:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString*)identifier {
self = [super initWithStyle:style reuseIdentifier:identifier];
if (self) {
// WORKS!
// cell's backgroundview (selected)
UIView *selectedView = [[UIView alloc] init];
selectedView.backgroundColor = [UIColor someColor..];
self.selectedBackgroundView = selectedView;
// DOESN'T WORK
// cell's background (normal)
UIView *normalView = [[UIView alloc] init];
normalView.backgroundColor = [UIColor someColor..];
self.backgroundView = normalView;
}
return self;
}
but I can't find a way to change the background of the cell when it's not selected (self.backgroundView). I know that there's an associated TTStyledTextLabel subview in the TTStyledTextTableItemCell class, but I still have no success customizing it.
Is there an easy way to achieve this??
Thanks
We have a window filled with little view squares (think of a Calculator).
For a specific view on the window we want display a single string in the view without using the Interface Builder to add the string.
We need to be able to change the string and have the view refresh.
How do we programmatically add a string to a view and show it?
Update:
Ok here is the code we have currently. Nothing special in the header file.
I suppose the real quandry is considering we can easily get the background color to change, why is it that our text is just not showing??
Both versions are in there, would be happy to get 'apples' or 'oranges' displaying.
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
bgString = #"orange";
UILabel* aLabel = [[UILabel alloc] init];
aLabel.text = #"apple";
self.textLabel = aLabel;
[aLabel release];
[self addSubview:textLabel];
}
return self;
}
- (void)drawRect:(CGRect)rect {
// Drawing code
[[UIColor yellowColor] setFill];
UIRectFill(rect);
[self drawStringCenteredIn:rect];
}
- (void)drawStringCenteredIn:(CGRect)r {
//CGSize strSize = [bgString size];
CGPoint strOrigin;
strOrigin.x = r.origin.x; //+ (r.size.width - 10)/2;
strOrigin.y = r.origin.y; //+ (r.size.height - 10)/2;
//[bgString drawAtPoint:strOrigin withFont:[UIFont fontWithName:#"Helvetica" size:10]];
[textLabel drawTextInRect:r];
}
In your view controller's .h:
#interface MyViewController
{
UILabel* label;
}
#property (nonatomic, retain) UILabel* label;
In your view controller's .m:
- (void)dealloc
{
[label release];
[super dealloc];
}
- (void)viewDidLoad
{
[super viewDidLoad];
UILabel* aLabel = [[UILabel alloc] init];
aLabel.text = #"Initial Text";
self.label = aLabel;
[aLabel release];
[self.view addSubview:aLabel];
}
- (void)viewDidUnload
{
[self.label removeFromSuperview];
self.label = nil;
}
// Call this when you need to update the label
- (void)updateLabel
{
self.label.text = #"Some updated text";
}
Did that from memory but it should work.
Try this:
UILabel* aLabel = [[UILabel alloc] initWithFrame:[self bounds]];
If you are creating the label manually, you need to set it's frame manually too.
Frame itself is size and position inside parent view(superview).
In my example i've set the frame of label to occupy the entire view. If you need your custom size you can use:
UILabel* aLabel = [[UILabel alloc] initWithFrame:CGRectMake(x,y,width,height)];
Where (x,y) - position of the top left corner of your label.
How about creating a UILabel and adding it to the view?
If you subclass the UIView, you can draw your string in the view's drawRect. This allows great flexibility in modifying the text, its appearance, and its placement (you can even animate it around, spin, rotate, etc.)
Call setNeedsDisplay on the view after you change your NSString. Then do an drawAtPoint:withFont: on the NSString when the drawRect is called.