Customize UILabel's Behavior - iphone

I am new to iphone.i found UILabel instance methodes very hard for me to implement.how can i use it.how can i customize the appearance of your text of a UIlabel further by subclassing UILabel.Plz i need little help to initiate.Foe example i have a label in my viewController how can i custmize it's text and hoe to subclass
.thanks in advance.

You can use so many properties of a UILabel like:
UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(5, 5, 100, 40)];
lbl.font = [UIFont fontWithName:#"Helvetica" size:12.0]; // For setting font style with size
lbl.textColor = [UIColor whiteColor]; //For setting text color
lbl.backgroundColor = [UIColor clearColor]; // For setting background color
lbl.textAlignment = UITextAlignmentCenter; // For setting the horizontal text alignment
lbl.numberOfLines = 2; // For setting allowed number of lines in a label
lbl.lineBreakMode = UILineBreakModeWordWrap; // For setting line break mode
lbl.text = #"TitleText"; // For setting the text inside the label
Let me know if any thing other than this you want to know!!
The two methods
- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines
{
return CGRectInset(bounds, MARGIN, MARGIN);
}
- (void)drawTextInRect:(CGRect)rect
{
[super drawTextInRect: CGRectInset(self.bounds, MARGIN, MARGIN)];
}
We are using CGRectInset to create a rectangle that is either larger or smaller than an existing rectangle (bounds).
For Smaller rectangle, use positive values as MARGIN
For Larger rectangle, use positive values as MARGIN
All the best!!!

Related

Formatting UITableViewCell

I have a UITableView cell and I need to set it's label to "Sometext (number)". I can do that, but I need the "(number)" to be grayish, how can I do that? Here's an image which might make what I am trying to ask clearer:
I need the 12, 24, 48, 96 to be gray just like in this picture.
Thanks.
You need two UILabels, You'll have the
label1.textColor = [UIColor blackColor];
label2.textColor = [UIColor grayColor];
now then that's the most obvious part, when you set your text on your label1 you'll have to do a
label1.text = ...;
CGSize newsize = [label1.text sizeWithFont:label1.font constraintToSize:CGSizeMake(320, label1.frame.size.height)];
label2.frame = CGRectMake(label1.frame.origin.x + newsize.width + 5., label2.frame.origin.y, label2.frame.size.width, label2.frame.size.height);
so they stay close like they're one label.
you can set text label text color as -
[cellView.textLabel setTextColor:[UIColor grayColor]];

iOS: UILabel dynamic height using sizeWithFont:constrainedToSize:lineBreakMode: not working

I am trying to give my UILabel dynamic height so that my layout of other labels looks correct in both landscape and portrait.
In portrait, my text wraps to the second line, in landscape it does not. So, when using sizeWithFont:constrainedToSize:lineBreakMode: I get the same height when rotating both ways, when I had assumed it would be a larger number when the text was 2 lines.
How can I get the height of my UILabel when it has two lines of text or more (portrait) and get the new height which is one line, when in landscape?
I guess I am not understanding how to get dynamic height working...
UILabel *itemTitle = [[UILabel alloc] initWithFrame:CGRectMake(10.0f, top, screen.size.width - 20, 200.0f)];
itemTitle.text = self.newsAsset.title;
itemTitle.adjustsFontSizeToFitWidth = NO;
itemTitle.autoresizingMask = UIViewAutoresizingFlexibleWidth;
itemTitle.font = [UIFont boldSystemFontOfSize:18.0];
itemTitle.textColor = [UIColor blackColor];
itemTitle.shadowColor = [UIColor whiteColor];
itemTitle.shadowOffset = CGSizeMake(0, 1);
itemTitle.backgroundColor = [UIColor blueColor];
itemTitle.lineBreakMode = UILineBreakModeWordWrap;
itemTitle.numberOfLines = 0;
[itemTitle sizeToFit];
// Set the height
CGSize maximumLabelSize = CGSizeMake(300,9999);
CGSize titleSize = [itemTitle.text sizeWithFont:itemTitle.font constrainedToSize:maximumLabelSize lineBreakMode:itemTitle.lineBreakMode];
NSLog(#"Height: %.f Width: %.f", titleSize.height, titleSize.width);
//Adjust the label the the new height
CGRect newFrame = itemTitle.frame;
newFrame.size.height = titleSize.height;
itemTitle.frame = newFrame;
// Add them!
[headerView addSubview:itemTitle];
[itemTitle release];
top += titleSize.height;
change the line where you set maximumLabelSize to
CGSize maximumLabelSize = CGSizeMake(headerView.bounds.size.width, CGFLOAT_MAX);
In your code as it is now, in either orientation you will get the same width and height, since you always pass a width of 300 to the sizeWithFont method. If you make it dynamic, maybe the result of the sizeWithFont will also change dynamically.

How to rotate viewForHeaderInSection

UITableView has custom header UIView, which contains UILabel. Since table has also section index at right side, I want to center the label in remaining space.
Problem is how to "center" label in same way, when device is rotated to landscape! I've tried both Interface Builder and code-only and something is always wrong.
Restrictions:
Label is as narrow as possible
Label must not be resized
Label must be always centered inside table width minus section index
One easy way to fix this would be making section header view detached from tableView right side. Tried to do it, failed. Here's some code from viewForHeaderInSection:
CGRect frame = CGRectMake(0, 0, tableView.bounds.size.width - 32, 50.0f);
// MAGIC 32 for SectionIndexTitles
UIView *view = [[[UIView alloc] initWithFrame:frame] autorelease];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
label.font = [UIFont fontWithName:#"Courier" size:20];
label.text = #"Section title long";
label.textAlignment = UITextAlignmentCenter;
label.backgroundColor = [UIColor redColor];
CGSize labelSize = [label.text sizeWithFont:label.font
constrainedToSize:frame.size
lineBreakMode:UILineBreakModeClip];
label.frame = CGRectMake(0, 0, labelSize.width, labelSize.height);
label.center = CGPointMake(frame.size.width/2.0f, kHeaderHeight/2.0f);
label.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
Any ideas welcome! Can't even recall how many different ways I have failed :)
Hey, set up as following in the IB:
Disable all autoresizing functionalities (no flexible width, height, nor any left, bottom, top, right).
Should do the job :)
To support the magic 32 pixels, try to position your Label as you need it.
That means:
Position it in the center of your UIView and move it 16 pixels to the left, now don't change the frame programmatically, else the "wonderful" auto-positiong will be manipulated what we don't really want to :)

iPhone UILabel text soft shadow

I know soft shadows are not supported by the UILabel out of the box, on the iPhone. So what would be the best way to implement my own one?
EDIT:
Obviously I will subclass the UILabel and draw in the -drawRect:
My question is, how do I get the contents of the label as graphics and draw around them, blur them etc...
EDIT 2:
I returned to this question about a year later. In the meantime I've built a class that allows you to easily add soft shadow to a label and tweak it's radius etc and also to draw gradients on the text itself. You can find it on GitHub: https://github.com/doukasd/iOS-Components/tree/master/Views
As of 3.2 there is direct support for shadows in the SDK.
label.layer.shadowColor = [label.textColor CGColor];
label.layer.shadowOffset = CGSizeMake(0.0, 0.0);
#import <QuartzCore/QuartzCore.h> and play with some parameters:
label.layer.shadowRadius = 3.0;
label.layer.shadowOpacity = 0.5;
And, if you find your shadow clipped by the label bounds:
label.layer.masksToBounds = NO;
finally set
label.layer.shouldRasterize = YES;
I advise you to use the shadowColor and shadowOffset properties of UILabel:
UILabel* label = [[UILabel alloc] init];
label.shadowColor = [UIColor whiteColor];
label.shadowOffset = CGSizeMake(0,1);
This answer to this similar question provides code for drawing a blurred shadow behind a UILabel. The author uses CGContextSetShadow() to generate the shadow for the drawn text.
Additionally to IIDan's answer:
For some purposes it is necessary to set
label.layer.shouldRasterize = YES
I think this is due to the blend mode that is used to render the shadow. For example I had a dark background and white text on it and wanted to "highlight" the text using a black shadowy glow. It wasn't working until I set this property.
Apply the (soft) shadow on the view's layer, like this:
UILabel *label = [[UIabel alloc] init];
label.layer.shadowColor = [[UIColor whiteColor] CGColor];
label.layer.shadowOpacity = 1.0;
To keep things up to date: Creating the shadow in Swift is as easy as that:
Import the QuartzCore Framework
import QuartzCore
And set the shadow attributes to your label
titleLabel.shadowColor = UIColor.blackColor()
titleLabel.shadowOffset = CGSizeMake(0.0, 0.0)
titleLabel.layer.shadowRadius = 5.0
titleLabel.layer.shadowOpacity = 0.8
titleLabel.layer.masksToBounds = false
titleLabel.layer.shouldRasterize = true
_nameLabel = [[UILabel alloc] initWithFrame:CGRectZero];
_nameLabel.font = [UIFont boldSystemFontOfSize:19.0f];
_nameLabel.textColor = [UIColor whiteColor];
_nameLabel.backgroundColor = [UIColor clearColor];
_nameLabel.shadowColor = [UIColor colorWithWhite:0 alpha:0.2];
_nameLabel.shadowOffset = CGSizeMake(0, 1);
i think you should use the [UIColor colorWithWhite:0 alpha:0.2] to set the alpha value.
I tried almost all of these techniques (except FXLabel) and couldn't get any of them to work with iOS 7. I did eventually find THLabel which is working perfectly for me. I used THLabel in Interface Builder and setup User Defined Runtime Attributes so that it's easy for a non programmer to control the look and feel.
https://github.com/MuscleRumble/THLabel
This like a trick,
UILabel *customLabel = [[UILabel alloc] init];
UIColor *color = [UIColor blueColor];
customLabel.layer.shadowColor = [color CGColor];
customLabel.layer.shadowRadius = 5.0f;
customLabel.layer.shadowOpacity = 1;
customLabel.layer.shadowOffset = CGSizeZero;
customLabel.layer.masksToBounds = NO;
I wrote a library that provides a UILabel subclass with soft shadow support and a bunch of other effects:
https://github.com/nicklockwood/FXLabel
In Swift 3, you can create an extension:
import UIKit
extension UILabel {
func shadow() {
self.layer.shadowColor = self.textColor.cgColor
self.layer.shadowOffset = CGSize.zero
self.layer.shadowRadius = 3.0
self.layer.shadowOpacity = 0.5
self.layer.masksToBounds = false
self.layer.shouldRasterize = true
}
}
and use it via:
label.shadow()
Subclass UILabel, as stated, then, in drawRect:, do [self drawTextInRect:rect]; to get the text drawn into the current context. Once it is in there, you can start working with it by adding filters and whatnot. If you want to make a drop shadow with what you just drew into the context, you should be able to use:
CGContextSetShadowWithColor()
Look that function up in the docs to learn how to use it.
As of iOS 5 Apple provides a private api method to create labels with soft shadows.
The labels are very fast: I'm using dozens at the same time in a series of transparent views and there is no slowdown in scrolling animation.
This is only useful for non-App Store apps (obviously) and you need the header file.
$SBBulletinBlurredShadowLabel = NSClassFromString("SBBulletinBlurredShadowLabel");
CGRect frame = CGRectZero;
SBBulletinBlurredShadowLabel *label = [[[$SBBulletinBlurredShadowLabel alloc] initWithFrame:frame] autorelease];
label.backgroundColor = [UIColor clearColor];
label.textColor = [UIColor whiteColor];
label.font = [UIFont boldSystemFontOfSize:12];
label.text = #"I am a label with a soft shadow!";
[label sizeToFit];
While it's impossible to set a blur radius directly on UILabel, you definitely could change it by manipulating CALayer.
Just set:
//Required properties
customLabel.layer.shadowRadius = 5.0 //set shadow radius to your desired value.
customLabel.layer.shadowOpacity = 1.0 //Choose an opacity. Make sure it's visible (default is 0.0)
//Other options
customLabel.layer.shadowOffset = CGSize(width: 10, height: 10)
customLabel.layer.shadowColor = UIColor.black.cgColor
customLabel.layer.masksToBounds = false
What I hope will help someone and other answers failed to clarify is that it will not work if you also set UILabel Shadow Color property directly on Interface Builder while trying to setup .layer.shadowRadius.
So if setting label.layer.shadowRadius didn't work, please verify Shadow Color for this UILabel on Interface Builder. It should be set to default. And then, please, if you want a shadow color other than black, set this color also through .layer property.
Subclass UILabel, and override -drawInRect:

iPhone UILabel sizeWithFont:

I'm trying to measure the visual size of a NSString that takes into account the number of lines I can render. However, sizeWithFont doesn't take into account numberOfLines property? So my layout algorithm positions everything lower than they actually need to be.
_price = [[UILabel alloc] init];
_price.text = myPriceValue;
_price.lineBreakMode = UILineBreakModeWordWrap;
_price.numberOfLines = 3;
_price.backgroundColor = [UIColor clearColor];
_price.textColor = TTSTYLEVAR(colorPrice);
/// the follow code ignores numberOfLines and just tells me the size of the whole block.
// I'd like it to be aware of numberOfLines
//
CGSize priceSize = [_price.text sizeWithFont:_price.font
constrainedToSize:CGSizeMake(maxWidth, CGFLOAT_MAX)
lineBreakMode:UILineBreakModeWordWrap];
Does anyone know how to do this using the iPhone SDK?
Instead of CGFLOAT_MAX for the max height of your text calculation, try getting the size of one line with this:
[_price.text sizeWithFont:_price.font].height
and then multiplying that by the maximum # of lines you want, then plugging that into the height of the size you are constraining yourself to. It'd probably look like this:
_price = [[UILabel alloc] init];
_price.text = myPriceValue;
_price.lineBreakMode = UILineBreakModeWordWrap;
_price.numberOfLines = 3;
_price.backgroundColor = [UIColor clearColor];
_price.textColor = TTSTYLEVAR(colorPrice);
CGFloat lineHeight = [_price.text sizeWithFont:_price.font].height;
CGSize priceSize = [_price.text sizeWithFont:_price.font
constrainedToSize:CGSizeMake(maxWidth, lineHeight * _price.numberOfLines)
lineBreakMode:UILineBreakModeWordWrap];
Don't use this if you ever set number of lines to 0 as your max height will be 0 in that case; you should use CGFLOAT_MAX then.
Use the UILabel's sizeToFit instead of sizeWithFont: to layout a multi-line UILabel, since sizeWithFont: will truncate the string (see apple docs). The following code reduces the font size of a label until the text fit into a the specified size... multiple lines of text will be used as soon as they fit into the specified height:
-(void)setFontSizeOfMultiLineLabel: (UILabel*)label
toFitSize: (CGSize) size
forMaxFontSize: (CGFloat) maxFontSize
andMinFontSize: (CGFloat) minFontSize
startCharacterWrapAtSize: (CGFloat)characterWrapSize{
CGRect constraintSize = CGRectMake(0, 0, size.width, 0);
label.frame = constraintSize;
label.lineBreakMode = UILineBreakModeWordWrap;
label.numberOfLines = 0; // allow any number of lines
for (int i = maxFontSize; i > minFontSize; i--) {
if((i < characterWrapSize) && (label.lineBreakMode == UILineBreakModeWordWrap)){
// start over again with lineBreakeMode set to character wrap
i = maxFontSize;
label.lineBreakMode = UILineBreakModeCharacterWrap;
}
label.font = [label.font fontWithSize:i];
[label sizeToFit];
if(label.frame.size.height < size.height){
break;
}
label.frame = constraintSize;
}
}
Call this with a label that has your favorite text and font:
UILabel *label = [[UILabel alloc] initWithFrame: CGRectZero];
label.backgroundColor = [UIColor clearColor];
label.textColor = [UIColor whiteColor];
label.text = text;
label.font = [UIFont fontWithName: #"Helvetica" size: 16];
[self setFontSizeOfMultiLineLabel: label toFitSize: CGSizeMake(200, 44) forMaxFontSize: 16 andMinFontSize: 8 startCharacterWrapAtSize: 11];
The startCharacterWrapAtSize parameter lets you choose to use characterWrap starting at the giving font size. This should save space in the case wordWrap would use really small fonts.
edit: bugfix
Instead of trying to do it in one call, do something like this (pardon the pseudocode, it's late):
NSString *s = _price.text;
UIFont *font = _price.font;
CGFloat fontSize = font.pointSize;
while (TRUE)
{
CGSize priceSize = [s sizeWithFont: font constrainedToSize:
CGSizeMake(maxWidth, fontSize) lineBreakMode: UILineBreakModeWordWrap];
if ( /* priceSize is satisfactory */ )
{
break; // Make sure this exits, eventually!!!
}
fontSize -= 1.0; // or a smaller decrement if you like
font = // new, smaller font
}
The correct answer is, of course, you need to set numberOfLines to 0, which will cause the framework to compute the result with however many lines it needs. See also this question.
Of course it doesn't take it into account, since nothing being called or passed in has that information. You're strictly working with strings, sizes, and fonts. It's the label that has the number of lines in it.
I'm not sure what exactly your problem is; are you getting a size that's too tall or too short, or what? You can find out the number of lines of text by dividing the height of the result by the height of the font, which is the value of the ascender plus the descender, I believe.