I'm trying to create a reusable 3-2-1 countdown timer by subclassing a UIView.
Basically, the way I want it to work is when the begin button (which I created on my main view controller via storyboard) is clicked, I want to init and add a subview to my main superview. I have it working - the subview is being rendered - but I can't seem to get a label to display from within my subview.
CountDownView.m
#import "CountDownView.h"
#implementation CountDownView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor whiteColor];
[self startCountdown];
}
return self;
}
- (void)startCountdown
{
UILabel *countTextLabel = [[UILabel alloc] initWithFrame:self.frame];
[countTextLabel setTextColor:[UIColor blackColor]];
[countTextLabel setBackgroundColor:[UIColor clearColor]];
[countTextLabel setFont:[UIFont fontWithName: #"Trebuchet MS" size: 14.0f]];
[self addSubview:countTextLabel];
countTextLabel.text = #"test"; // just trying to get some dummy text to work for now.
}
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
#end
So how do I add the label to the subview?
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 drawing three rectangles in order to show the loading, however I want to input Alphabets in those rectangles, how can I put letters in that.
My Function:
- (void)configUI {
self.backgroundColor = [UIColor clearColor];
UIView *rect1 = [self drawRectAtPosition:CGPointMake(0, 0)];
UIView *rect2 = [self drawRectAtPosition:CGPointMake(20, 0)];
UIView *rect3 = [self drawRectAtPosition:CGPointMake(40, 0)];
[self addSubview:rect1];
[self addSubview:rect2];
[self addSubview:rect3];
[self doAnimateCycleWithRects:#[rect1, rect2, rect3]];
}
I want to insert the letter "A" in rect1, "B" in rect2 and "C" in rect3.
Use UILabel instead of UIView. Set the label text. (Note that a UILabel has a background color just like a UIView.)
To draw a string on view, you need to create a subclass of UIView. Import this view in your view controller and create above views as object of custom view.
In custom view there is a view override method -
- (void)drawRect:(CGRect)rect;
This is the place where you can draw string and set attributes for drawing.
For example: Custom view class
CustomView.h
#import <UIKit/UIKit.h>
#interface CustomView : UIView
#property (nonatomic, strong) NSString *drawString;
#end
CustomView.m
#import "CustomView.h"
#implementation CustomView
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
}
return self;
}
- (void)drawRect:(CGRect)rect {
NSMutableParagraphStyle *textStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy];
textStyle.lineBreakMode = NSLineBreakByClipping;
textStyle.alignment = NSTextAlignmentCenter;
NSDictionary *attributes = #{
NSParagraphStyleAttributeName: textStyle,
// Text font
NSFontAttributeName : [UIFont fontWithName:#"HelveticaNeue" size:20.0],
// Text color
NSForegroundColorAttributeName : [UIColor orangeColor]
};
[self.drawString drawInRect:rect withAttributes:attributes];
}
#end
Now in your code create view object type of this custom class:
- (void)configUI {
self.backgroundColor = [UIColor clearColor];
CustomView *rect1 = [self drawRectAtPosition:CGPointMake(0, 0)];
CustomView *rect2 = [self drawRectAtPosition:CGPointMake(20, 0)];
CustomView *rect3 = [self drawRectAtPosition:CGPointMake(40, 0)];
// This will draw text to view
[rect1 setDrawString:#"A"];
[rect2 setDrawString:#"B"];
[rect3 setDrawString:#"C"];
[rect1 setBackgroundColor:[UIColor whiteColor]];
[rect2 setBackgroundColor:[UIColor whiteColor]];
[rect3 setBackgroundColor:[UIColor whiteColor]];
[self addSubview:rect1];
[self addSubview:rect2];
[self addSubview:rect3];
[self doAnimateCycleWithRects:#[rect1, rect2, rect3]];
}
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.
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];
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.