sizeWithFont:constrainedToSize:lineBreakMode: not accurate? - iphone

sizeWithFont:constrainedToSize:lineBreakMode: don't seem to be returning me the correct width. After these codes are executed, I see that part of the string in the label is chopping off, which means I've to manually add a few pixels to the size. Am I missing something?
I've a UILabel:
theLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, LABELWIDTH, LABELHEIGHT)];
theLabel.lineBreakMode = UILineBreakModeWordWrap;
theLabel.numberOfLines = 0;
[theLabel setFont:[UIFont fontWithName:#"MarkerFelt-Wide" size:16]];
theLabel.textColor = [UIColor blackColor];
theLabel.textAlignment = UITextAlignmentLeft;
theLabel.backgroundColor = [UIColor clearColor];
I tried to programmatically modify the size of the label using the following:
CGSize maximumLabelSize = CGSizeMake(LABELWIDTH, 10000);
CGSize expectedLabelSize = [someString sizeWithFont:theLabel.font constrainedToSize:maximumLabelSize lineBreakMode:theLabel.lineBreakMode];
theLabel.text = someString;
CGRect newFrame = theLabel.frame;
newFrame.size.height = expectedLabelSize.height;
newFrame.size.width = newFrame.size.width+50;
theLabel.frame = newFrame;

Ok, well, the first thing I'll say is that there are some very useful ways to deal with frames that you currently aren't employing. For example, your code,
CGRect newFrame = theLabel.frame;
newFrame.size.height = expectedLabelSize.height;
newFrame.size.width = newFrame.size.width+50;
theLabel.frame = newFrame;
Can be rewritten with functions from CGGeometry,
CGFloat widthOffset = 50.0f;
theLabel.frame = CGRectOffset(CGRectInset(theLabel.frame, widthOffset, 0.0f), widthOffset / 2.0f, 0.0f);
However, if your code worked as it was intended, you would not need to do this at all. You can go two routes,
[theLabel sizeToFit];
Or, this should also work,
theLabel.frame = CGRectMake(theLabel.frame.origin.x, theLabel.frame.origin.y, expectedLabelSize.width, expectedLabelSize.height);
No where in your earlier code did you change the width of theLabel to match the expected width. Notice, you wrote newFrame.size.width = newFrame.size.width+50 and that should be newFrame.size.width = expectedLabelSize.width.

Related

How to animate the movement of a UILabel

I am moving a UILabel around in my app and I would like it to change location and size over a few frames instead of jumping location. I am using Objective-c and cocoa developing for the Iphone. Can anyone help me out?
The easiest way to do it is like:
CGRect endFrame = /*The frame of your label in end position*/
[UIView animateWithDuration:0.5 animations:^{
myLabel.frame = endFrame;
}];
This Code is Helpful for your problem
#define FONT_SIZE 14
#define DURATION 10
#define DELAY 10
-(void)viewWillAppear:(BOOL)animated {
NSString* string = #"My Label";
CGSize framesize = [string sizeWithFont:[UIFont fontWithName:#"Copperplate" size:FONT_SIZE]];
// Origin
float x0 = 0;
float y0 = 0;
CGRect appFrame = [[UIScreen mainScreen] applicationFrame];
CGFloat appFrameWidth = appFrame.size.width;
CGFloat appFrameHeight = appFrame.size.height;
// Destination
float x1 = appFrameWidth - framesize.width;
float y1 = appFrameHeight - framesize.height;
UILabel* label = [[UILabel alloc]initWithFrame:CGRectMake(x0, y0, framesize.width, framesize.height)];
label.backgroundColor = [UIColor clearColor];
label.text = string;
label.shadowColor = [UIColor grayColor];
label.shadowOffset = CGSizeMake(1,2);
label.font = [UIFont fontWithName:#"Copperplate" size:FONT_SIZE];
[self.view addSubview:label];
[UIView animateWithDuration:DURATION
delay:DELAY
options:UIViewAnimationOptionAllowUserInteraction
animations:^{
label.frame = CGRectMake(x1, y1, framesize.width, framesize.height);
}
completion:^(BOOL finished){
[label removeFromSuperview];
}];
}

I am using UITextView on a scroll view ...and I want it to auto expand when I write something in it ......

textViewBusiness = [[UITextView alloc] initWithFrame:CGRectMake(25,332,268,60)];
textViewBusiness.text=strMyBusiness;
textViewBusiness.editable=NO;
textViewBusiness.font = [UIFont fontWithName:#"Arial" size: 17.0];
textViewBusiness.layer.borderWidth = 2.0f;
textViewBusiness.layer.borderColor = [[UIColor grayColor] CGColor];
textViewBusiness.backgroundColor = [UIColor clearColor];
[textViewBusiness setTextColor:[UIColor blackColor]];
[self.scrollView addSubview: textViewBusiness];
CGRect frame = textViewBusiness.frame;
frame.size.height = textViewBusiness.contentSize.height;
textViewBusiness.frame = frame;
with the increase in contents i want to increase the size of text field....
This code is not working for me ...
Thanks
You don't need to take UITextView for showing un-editable text. Besides this you can use UILabel and you can find out the height of label at run time. Each time the content vary in size set frame of UILabel accordingly.
Use this to find out height of your label at run time
- (CGFloat) heightOfTextLabel:(NSString *) contentText
{
CGSize constraint = CGSizeMake(268,4000);
CGSize size = [contentText sizeWithFont:[UIFont fontWithName:#"Arial" size: 17.0] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
return size.height;
}
This method would return you a variable height of the content each time.
Now set this height to your UILabel
CGFloat heightOfLabel = [self heightOfTextLabel:strMyBusiness];
UILabel* textToShowLabel = [[UILabel alloc] initWithFrame:CGRectMake(25,332,268,heightOfLabel)];
textToShowLabel.text=strMyBusiness;
textToShowLabel.font = [UIFont fontWithName:#"Arial" size: 17.0];
textToShowLabel.layer.borderWidth = 2.0f;
textToShowLabel.layer.borderColor = [[UIColor grayColor] CGColor];
textToShowLabel.backgroundColor = [UIColor clearColor];
[textToShowLabel setTextColor:[UIColor blackColor]];
[self.scrollView addSubview: textToShowLabel];
You need to divide your code into 2 fragments, then place them into proper places, then your code should work.
Fragment 1 (in my test, I place this fragment in viewDidLoad):
textViewBusiness = [[UITextView alloc] initWithFrame:CGRectMake(25,332,268,60)];
textViewBusiness.text=strMyBusiness;
textViewBusiness.editable=NO;
textViewBusiness.font = [UIFont fontWithName:#"Arial" size: 17.0];
textViewBusiness.layer.borderWidth = 2.0f;
textViewBusiness.layer.borderColor = [[UIColor grayColor] CGColor];
textViewBusiness.backgroundColor = [UIColor clearColor];
[textViewBusiness setTextColor:[UIColor blackColor]];
[self.scrollView addSubview: textViewBusiness];
Ensure that the above fragment run, and your text view is displayed in the screen, then run the second fragment. If your text view is not displayed in the screen, then the contentView is not initialized, and the height is undefined.
Fragment 2 (in my test, I place this fragment in viewDidAppear):
CGRect frame = textViewBusiness.frame;
frame.size.height = textViewBusiness.contentSize.height;
textViewBusiness.frame = frame;
Good luck!
GrowingTextView is a reusable iOS compenent that does exactly what you need, you can find it on GitHub here .
I hope this helps.

UIScrollView and UITextView autosizing possible?

I have a view that is pushed onto the Screen via navigation controllers:
Inside is a UIScrollView.
Then inside the UIScrollView are a few static objects like Images and Labels.
Then comes the hard bit, There is a UITextView with its text loaded from different text files of varying length.
I need to be able to have the UITextView size dynamically to its contents, and the same for the UIScrollView. Is this possible?
float length = [yourText length];
textview.frame = CGRectMake(44, 87, 923, ceilf(length/142)*25);
Here 25 is the constant value assumed as text font width. From this you can set scrollview frame reference to the textview frame.
You can do that with the help of following code. I had done that code for Label and same way you can do that with the help of text-field.
NSString *cellText = "Text Of Your Text-Field";
UIFont *cellFont = [UIFont fontWithName:#"Your Font Name" size:FONT_SIZE];//UIFont *cellFont = [UIFont fontWithName:#"Helvetica-Bold" size:13.0];
CGSize constraintSize = CGSizeMake(#"Width Of Your Text-Field", MAXFLOAT);//CGSize constraintSize = CGSizeMake(220.0f, MAXFLOAT);
CGSize labelSize = [cellText sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];
int height = labelSize.height;
frame.origin.x = Starting Position of X;
frame.origin.y = Starting Position of Y;
frame.size.width = Width Of Your TextField;
frame.size.height = height;
UILabel *lblName = [[[UILabel alloc] initWithFrame:frame] autorelease];
lblName.numberOfLines = 0;
lblName.lineBreakMode = UILineBreakModeWordWrap;
lblName.textAlignment = UITextAlignmentLeft;
lblName.textColor = [UIColor whiteColor];
lblName.backgroundColor = [UIColor clearColor];
lblName.font = [UIFont boldSystemFontOfSize:13.0];
And same way you can do For the Scrollview. Just you have to set the Frame of that scrollview and you are done.
Yes you could do something like this:
if ([textView length] > int//any number you want) {
textView.frame = CGRectMake(//just adjust the size an position here);
scrollView.contentSize = CGSizeMake(//adjust scrollView size)
}
else if ([textView length] > int//just another number) {
// you can continue looping that for how often you want
}
For the int in the if statement you check how long the text is. Based on that you adjust the size of both the scrollView and textView.

UILabel not aligning perfectly center when wrapping

See image for example: http://img25.imageshack.us/img25/6996/90754687.png
The grey background indicates the size of the UILabel frame.
For some reason, the first line of wrapped text doesn't seem to always center, even though I'm using UITextAlignmentCenter.
Here's the code I use to set up my labels:
self.titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
titleLabel.font = [UIFont boldSystemFontOfSize:fontHeight];
titleLabel.backgroundColor = [UIColor grayColor];
titleLabel.numberOfLines = 2;
titleLabel.lineBreakMode = UILineBreakModeMiddleTruncation;
NSString * title = file.name;
CGSize maximumSize = CGSizeMake(thumbnailWidth+4,fontHeight * 3);
UIFont * font = [UIFont boldSystemFontOfSize:12];
CGSize stringSize = [title sizeWithFont:font constrainedToSize:maximumSize lineBreakMode:titleLabel.lineBreakMode];
CGRect stringFrame = CGRectMake(0, thumbnailHeight + thumbnailPadding, thumbnailWidth + 4, stringSize.height);
titleLabel.text = title;
titleLabel.frame = stringFrame;
titleLabel.textAlignment = UITextAlignmentCenter;
Is that because there are no spaces in the text? In IB it appears to react just like your getting, if you have no spaces. Setting the line break mode to character wrap tends to center the second lines to the first, but that may not be entirely what you want either.

How can I make text in a UILabel shrink font size

If a UILabel contains too much text, how can I setup my label so that it shrinks font-sizes?
Here is how I am setting up my UILabel:
descriptionLabel = [[UILabel alloc] initWithFrame:CGRectMake(200, 30, 130, 150)];
[descriptionLabel setFont:[Utils getSystemFontWithSize:14]];
[descriptionLabel setBackgroundColor:[UIColor clearColor]];
[descriptionLabel setTextColor:[UIColor whiteColor]];
descriptionLabel.numberOfLines = 1;
[self addSubview:descriptionLabel];
descriptionLabel.adjustsFontSizeToFitWidth = YES;
descriptionLabel.minimumFontSize = 10.0; //adjust to preference obviously
The following example is tested and verified on iPhone Simulator 3.1.2:
UILabel *descriptionLabel = [[UILabel alloc] initWithFrame:CGRectMake(90, 0, 200, 30)];
descriptionLabel.font = [UIFont systemFontOfSize:14.0];
descriptionLabel.minimumFontSize = 10.0;
descriptionLabel.adjustsFontSizeToFitWidth = YES;
descriptionLabel.numberOfLines = 1;
descriptionLabel.text = #"supercalifragilisticexpialidocious even thought he sound of it is something quite attrocious";
To resize the text in a multi-line UILabel, you can use this helper method (based on code from 11 Pixel Studios):
+ (void)resizeFontForLabel:(UILabel*)aLabel maxSize:(int)maxSize minSize:(int)minSize {
// use font from provided label so we don't lose color, style, etc
UIFont *font = aLabel.font;
// start with maxSize and keep reducing until it doesn't clip
for(int i = maxSize; i >= minSize; i--) {
font = [font fontWithSize:i];
CGSize constraintSize = CGSizeMake(aLabel.frame.size.width, MAXFLOAT);
// This step checks how tall the label would be with the desired font.
CGSize labelSize = [aLabel.text sizeWithFont:font constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];
if(labelSize.height <= aLabel.frame.size.height)
break;
}
// Set the UILabel's font to the newly adjusted font.
aLabel.font = font;
}
Set the adjustsFontSizeToFitWidth property to YES.
If you want the number of lines to also increase if needed, use Steve N's solution, with the if statement as so:
if(labelSize.height <= aLabel.frame.size.height)
{
aLabel.numberOfLines = labelSize.height / font.lineHeight;
break;
}