How to draw an UILabel in -drawRect:? - iphone

Must I also do all this crazy coordinate system conversion stuff here, or is an UILabel different from an UIImageView drawing in -drawRect: ?
There's a method called - (void)drawTextInRect:(CGRect)rect for that.
BUT the documentation says: "You should not call this method directly. This method should only be overridden by subclasses that want to modify the default drawing behavior for the label’s text."
So? How to draw it then in -drawRect:?

UILabel is different in that you don't need to manually draw text to alter the way it is presented. Subclassing UILabel and overriding -drawTextInRect: is the quickest way to alter the way a UILabel is rendered. For example,
- (void)drawTextInRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetShadowWithColor( context, shadowOffset, shadowRadius, [shadowColor CGColor] );
[super drawTextInRect:rect];
}
will add a shadow with a specific offset, radius, and color (as a UIColor instance) to any text that you draw in that UILabel. For an example of this in action, see a project I put together for a recent class.
However, if what you are looking to do is just draw text within another view, Vladimir's answer is the way to go.

If you perform custom drawing in your view you must not draw UILabel or another UI element but rather draw text itself. NSString has several methods for drawing in current context (look at NSString's UIKit extension docs for more methods):
- (CGSize)drawInRect:(CGRect)rect withFont:(UIFont *)font
- (CGSize)drawAtPoint:(CGPoint)point withFont:(UIFont *)font

Actually you can do it.
Try this:
UILabel *lblRef = [[UILabel alloc] initWithFrame:CGRectMake(x, y, width, height)];
lblRef.text = [refs objectAtIndex:barCount];
lblRef.adjustsFontSizeToFitWidth = TRUE;
lblRef.adjustsLetterSpacingToFitWidth = TRUE;
lblRef.textColor = self.color;
[lblRef setTextAlignment:NSTextAlignmentCenter];
lblRef.backgroundColor = [UIColor clearColor];
[self addSubview:lblRef];

Related

drawRect doesn't reflect changes made to layer

The UITableView I am using has a custom UItableViewCell. This custom cell has a subview (an UIView subclass) to it. I use the drawRect of the custom UIView subclass to place all the text to be displayed by the cell.
And in the drawRect (of UIView subclass) I do the following
/*
// This piece of code is called when setNeedsDisplay is called
*/
- (void)drawRect:(CGRect)rect
{
self.layer.cornerRadius = 10.0f;
self.layer.backgroundColor = [[UIColor orangeColor] CGColor];
self.layer.borderColor = [[UIColor lightGrayColor] CGColor];
self.layer.borderWidth = 3.0f;
}
However my custom cell is a black square like this
But I do see the intended behavior if I select the row. Like shown below
Whats going on ?
Your drawRect: method does not draw anything; the code that you put in there belongs in your initWithFrame: implementation.
You should manipulate the layer configuration in the initializer; in your drawRect: you should call functions of your CGContextRef based on the state of the view. For example, to draw some text you would use CGContextShowTextAtPoint, to draw some lines you would use CGContextAddLineToPoint, and so on.
See this question for information on the relationship between drawRect: and the CALayer of your UIView.
Try to set self.layer.masksToBounds = YES and (maybe) self.opaque = NO during your UIView's (the one where drawRect is overridden) initialization. (see this question)
Try to disable the selection highlight of the cell by using
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
You are doing one mistake:
Please go to the view in side the UItableViewCell and check the background color it may be black or something others, Reset it to clear color then check your result,

Placing Text in UITextField

textField.layer.backgroundColor = [UIColor lightGreenColorTransparent].CGColor;
textField.layer.cornerRadius = 8.0f;
textField.layer.borderColor = [UIColor lightGrayColor].CGColor;
textField.layer.borderWidth = 1.0f;
How can I set the text for about 5px to the right that there is more space between the border and the beginning of the text?
UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 5, 20)];
textField.leftView = paddingView;
textField.leftViewMode = UITextFieldViewModeAlways;
set the leftView property for padding the UITextField.
drawTextInRect:
Draws the receiver’s text in the specified rectangle.
- (void)drawTextInRect:(CGRect)rect
Parameters
rect
The rectangle in which to draw the text.
Discussion
You should not call this method directly. If you want to customize the drawing behavior for the text, you can override this method to do your drawing.
By the time this method is called, the current graphics context is already configured with the default environment and text color for drawing. In your overridden method, you can configure the current context further and then invoke super to do the actual drawing or you can do the drawing yourself. If you do render the text yourself, you should not invoke super.
Availability
Available in iOS 2.0 and later.
Declared In
UITextField.h
textField.contentInset = UIEdgeInsetsMake(4,8,0,0);

How can I change the placeholder color of a UITextField?

I have tried the two options everybody answers in this forum but nothing works for me... I have tried to override:
- (void)drawPlaceholderInRect:(CGRect)rect
and also:
[self.myTextField setValue:[UIColor redColor] forKeyPath:#"_placeholderLabel.textColor"];
but nothing happens... Still the same gray color... Maybe I have to inherit something, I don't know... Any suggestion?
the simplest way to do this:
UILabel *placeholderAppearance;
if (#available(iOS 9, *)) {
placeholderAppearance = [UILabel appearanceWhenContainedInInstancesOfClasses:#[[UITextField class]]];
} else {
placeholderAppearance = [UILabel appearanceWhenContainedIn:[UITextField class], nil];
}
placeholderAppearance.textColor = [UIColor redColor];
[EDITED]
After using this I got to know another bug, the above did the job but it also reset the color of all other labels in my view to Default Black. Then to overcome this, I had to sub class the UILabel class and use my class in all other labels in my view.
See drawPlaceholderInRect: of UITextField. You need to subclass UITextField and override this method for configuring graphics context with desired text color and call super implementation.
By the time this method is called, the current graphics context is
already configured with the default environment and text color for
drawing. In your overridden method, you can configure the current
context further and then invoke super to do the actual drawing or do
the drawing yourself. If you do render the text yourself, you should
not invoke super.
From iOS6 you can use the attributed placeholder:
textfield.attributedPlaceholder = [[NSAttributedString alloc] initWithString:textfield.placeholder attributes:#{NSForegroundColorAttributeName: [UIColor redColor]}];

Back Button in navigation controller

Its a very basic question - but i could not find the answer to it anywhere.
I would like a back button like the default one that shows up in a navigation bar, but with a image in the background.
Even with customization, how to calculate the size/length of the button as per the title?
Thanks a ton for the help,in advance!
UPDATE:
Thanks guys! but the answer that i finally implemented was this:
#implementation UINavigationBar (UINavigationBarCategory)
-(void)drawRect:(CGRect)rect
{
UIColor *color = [UIColor colorWithRed:(13.0/255.0) green:(183.0/255.0) blue:(255.0/255.0) alpha:1.0];
// use a custom color for the back button which i got using the digital color meter on my nav bar image :P
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColor(context, CGColorGetComponents( [color CGColor]));
CGContextFillRect(context, rect);
self.tintColor = color;
// use a custom background image for my navigation bar
UIImage *img = [UIImage imageNamed: Navigation_img];
[img drawInRect:CGRectMake(0,0,img.size.width,img.size.height)];
}//worked satisfactorily for me
#end
Create a UIButton using your own UIImage to mimic the shape you want.
The UIImage must be a stretchable type, that is, you would set the leftCapWidth to be the size of your back arrow
Set the UIButton's title to whatever you like
Create a new UIBarButtonItem using your new button as a custom view
Set this to your navigationItems leftBarButtonItem property.
The button will automatically size to fit your title.
Use sizeWithFont: NSString method to calculate the size of the title.
See NSString UIKit Additions Reference
To find out the width of specific text, you may use following methods.
NSString *str=#"Back";
CGSize sizeOfBack = [str sizeWithFont:[UIFont systemFontOfSize:14] constrainedToSize:CGSizeMake(30, CGFLOAT_MAX) lineBreakMode:UILineBreakModeWordWrap];
Let me explain above two statements.
the text that you want to have in your string.
sizewithfont method will allow you to calculate the size.
Here, sizeOfBack.width will give me the width acquired by 14System sized string.
Hope it helps to you. let me know by comments, if you have yet doubts regarding this.

iPhone UIStringDrawing usage

Could someone please explain to me how to draw a
string using UIStringDrawing instead of using a label? here is my code but for some reason it compiles and the screen is blank...
//
// MainViewController.m
// DotH
//
#define WINDOW_FRAME [[UIScreen mainScreen] bounds]
#define SCREEN_FRAME [UIScreen mainScreen].applicationFrame
#define GRAY [UIColor grayColor]
#define BLACK [UIColor blackColor]
#implementation MainViewController
- (void)loadView {
  UIView *view = [[UIView alloc] initWithFrame:SCREEN_FRAME];
  [view setBackgroundColor:GRAY];
  [BLACK setFill];
  NSString *string = #"Hey Dude!";
  [string drawAtPoint:CGPointMake(50, 50) withFont:[UIFont systemFontOfSize:14]];
  self.view = view;
  [view release];
}
#end
The line
[string drawAtPoint:CGPointMake(50, 50) withFont:[UIFont systemFontOfSize:14]];
needs to be in the view's drawRect: method.
This is because just before drawRect: is called, the rectangle passed as an argument to drawRect: is erased. So if you try to do custom drawing anywhere other than a view's drawRect: method, the stuff you draw will get erased whenever drawRect: is called. (Not to mention that calling drawAtPoint: is meaningless if not done by code within a UIView.)
You will need to make a custom subclass of UIView, and that subclass will need a custom drawRect: method. If you still want the view controller to be the entity responsible for deciding what string should be drawn and how, you should give your UIView subclass a method like
- (void)addString:(NSString *)string atPoint:(CGPoint)point withFont:(UIFont *)font;
That method can store that information, in, e.g., three NSMutableArrays (one of strings, one of points, and one of fonts), and increment a counter of how many strings have been added. Then, your view's drawRect: method can draw the strings described in those arrays. To add a string, your view controller just calls addString:atPoint:withFont: on your view.