In my project there is huge number of UIlabels. I have created one separate custom class for UILabel and I have set all label's properties in that class.
Here my main requirement is some labels' color is white and some labels' text color is black but color is not applying.
CustomUILabel class:-
#import "CustomLabel.h"
#implementation CustomLabel
-(void)layoutSubviews{
[self setupUI];
}
- (void)setupUI {
[self setTextAlignment:NSTextAlignmentLeft];
[self setFont:[UIFont fontWithName:#"Futura" size:14.0]];
[self setBackgroundColor:[UIColor clearColor]];
[self setTextColor:[UIColor blackColor]];
}
#end
Main class:-
#import "MainViewController.h"
#interface MainViewController (){
}
#end
#implementation MainViewController
#synthesize label1,label2;
- (void)viewDidLoad {
[super viewDidLoad];
label1.textColor = [UIColor whiteColor];
label2.textColor = [UIColor blackColor];
}
When you override layoutSubviews, you must call [super layoutSubviews]. But that's not your problem here. The problem is that you're calling setupUI in layoutSubviews, and you shouldn't. Layout happens after viewDidLoad, so your attempt to set the color in viewDidLoad gets overridden later during layout, when setupUI runs.
You should be calling setupUI from the init methods of your subclass:
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self setupUI];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
[self setupUI];
}
return self;
}
And you shouldn't override layoutSubviews at all in CustomLabel.
The problem is with your layoutSubview method and your setupUI method.
layoutSubviews is not the proper place to call setupUI. layoutSubviews can be called many times and is most likely being called a couple of times after viewDidLoad is called which is why the colors are being reset back to black.
And always call [super layoutSubviews]; in your layoutSubviews method.
The better place to call your setupUI method is from one or more of the appropriate init... methods and possibly awakeFromNib.
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'm trying to customise navigation bar in iOS 7. I create custom class that is subclass of UINavigationBar. And there I make the following changes:
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self setBarTintColor:[UIColor blackColor]];
[self setTranslucent:YES];
[self setAlpha:0.6f];
}
return self;
}
And there is no any changes, I set custom class in interface builder. What should I do?
Try to override initWithCoder, not initWithFrame, if You are using storyboard to create UINavigationBar.
In situations like that try to set breakpoint to method and check it this method get called at least
If you are using your custom view in IB, you should also override awakeFromNib and do some init there as well. In your code, it could be:
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self setup];
}
return self;
}
-(void)awakeFromNib {
[self setup];
}
-(void)setup {
[self setBarTintColor:[UIColor blackColor]];
[self setTranslucent:YES];
[self setAlpha:0.6f];
}
I can't intercept the init function that's getting called when it's getting created inside of the xib file.
I want to add borderline to it when it gets created so that I won't need to add it manually.
.h:
#import <UIKit/UIKit.h>
#interface UITextView (FITAddBorderline)
- (id) init;
- (id) initWithFrame:(CGRect)frame;
#end
.m:
#import "UITextView+FITAddBorderline.h"
#implementation UITextView (FITAddBorderline)
- (id) init
{
self = [super init];
if (self) {
[self addBorderline];
}
return self;
}
- (id) initWithFrame:(CGRect)frame {
self = [super init];
if (self) {
self.frame = frame;
[self addBorderline];
}
return self;
}
- (void) addBorderline {
//To make the border look very close to a UITextField
[self.layer setBorderColor:[[[UIColor grayColor] colorWithAlphaComponent:0.5] CGColor]];
[self.layer setBorderWidth:2.0];
//The rounded corner part, where you specify your view's corner radius:
self.layer.cornerRadius = 5;
self.clipsToBounds = YES;
}
#end
Views that come from NIBs are initialized with initWithCoder:
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
[self addBorderline];
}
return self;
}
As a side note, I would recommend changing what you are doing and use a subclass instead of a category. You can get yourself into some trouble overriding methods in a category. See more info here.
You just need to implement the awakeFromNib method:
-(void)awakeFromNib
{
[super awakeFromNib];
[self addBorderline];
}
I have recently started learning core graphics to draw on views, but every time I call setNeedsDisplay, the method runs but doesn't trigger drawRect. In my project, I have a view on a view controller. The view contains an if statement in drawRect that checks if a BOOL variable is YES or NO. If YES, it uses the code to draw a red circle. If NO, it draws a blue circle. In the BOOL's setter, it calls setNeedsDisplay. I create an instance of this view class in the ViewController and set the BOOL but the view is not redrawing. Why is the method not getting called? I posted the xcode files and code bits below.
Customview.m:
#import "CustomView.h"
#implementation CustomView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setup];
}
return self;
}
-(void)awakeFromNib{
[self setup];
}
-(void)setup{
_choice1 = YES;
}
-(void)setChoice1:(BOOL)choice1{
_choice1 = choice1;
[self setNeedsDisplay];
}
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
if (_choice1) {
UIBezierPath * redCircle = [UIBezierPath bezierPathWithOvalInRect:rect];
[[UIColor redColor]setFill];
[redCircle fill];
}else if (!_choice1){
UIBezierPath * blueCircle = [UIBezierPath bezierPathWithOvalInRect:rect];
[[UIColor blueColor]setFill];
[blueCircle fill];
}
}
#end
CustomView.h:
#import <UIKit/UIKit.h>
#interface CustomView : UIView
#property (nonatomic) BOOL choice1;
#end
ViewController.m:
#import "ViewController.h"
#import "CustomView.h"
#interface ViewController ()
- (IBAction)Change:(id)sender;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)Change:(id)sender {
CustomView * cv = [[CustomView alloc]init];
[cv setChoice1:NO];
}
#end
Full project: https://www.mediafire.com/?2c8e5uay00wci0c
Thanks
You need to create an outlet for your CustomView in your ViewController. Delete the code that creates the new CustomView instance and use _cv to refer to the customView.
#interface ViewController ()
- (IBAction)Change:(id)sender;
#property (weak,nonatomic) IBOutlet CustomView *cv;
#end
Then, in the storyboard, connect ViewController's cv outlet to the CustomView. Also, you'll need to implement the initFromCoder: method on CustomView.
- (id)initWithCoder:(NSCoder *)aDecoder {
if ((self = [super initWithCoder:aDecoder])) {
[self setup];
}
return self;
}
At the moment I'm subclassing a UISlider and in the drawRect setting the default values. I'm getting a strange result.
The slider min image is at the correct position but the slider max image has white space on the left. The slider image in the middle is to far right and the colour for maximumTackTintColor is on both sides of the slider.
- (void)drawRect:(CGRect)rect
{
// Drawing code
self.minimumTrackTintColor = [ThemeManager minimumTrackTintColorForSlider];
self.maximumTrackTintColor = [ThemeManager maximumTrackTintColorForSlider];
self.minimumValueImage = [UIImage imageNamed:#"sliderLeftDot"];
self.maximumValueImage = [UIImage imageNamed:#"sliderRightDot"];
[self setThumbImage:[UIImage imageNamed:#"sliderCentrePiece"] forState:UIControlStateNormal];
}
You're not calling [super drawRect:rect] and this causes the slide to never be drawn properly, however you should never override drawRect: unless you need to perform custom drawing.
The right place where to initialize defaults is the designated initializer(s). Being UISlider a subclass of UIView, you need to override both -initWithFrame: and -initWithCoder:, to handle both the cases in which the slider is created programmatically or via a nib.
For instance
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self commonInit];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
[self commonInit];
}
return self;
}
- (void)commonInit {
self.minimumTrackTintColor = [ThemeManager minimumTrackTintColorForSlider];
self.maximumTrackTintColor = [ThemeManager maximumTrackTintColorForSlider];
self.minimumValueImage = [UIImage imageNamed:#"sliderLeftDot"];
self.maximumValueImage = [UIImage imageNamed:#"sliderRightDot"];
[self setThumbImage:[UIImage imageNamed:#"sliderCentrePiece"] forState:UIControlStateNormal];
}
Do not put that code in the drawRect: method. Put it in the appropriate init method or put it in another method that you call when you want the slider customized.
Even better is to make used of the UIAppearance feature to set the tint colors for all sliders:
[[UISlider appearance] setMinimumTrackTintColor:someColor];
[[UISlider appearance] setMaximumTrackTintColor:someColor];