How can I draw multiple lines of text with drawAtPoint? - iphone

I am custom drawing some text:
point = CGPointMake(77, 5);
[[message valueForKey:#"user_login"] drawAtPoint:point forWidth:200
withFont:mainFont
minFontSize:MIN_MAIN_FONT_SIZE
actualFontSize:NULL
lineBreakMode:UILineBreakModeTailTruncation
baselineAdjustment:UIBaselineAdjustmentAlignBaselines];
How can I make it draw 5 lines? Equivalent to:
rect = CGRectMake(77, 25, 238, 68);
bodyLabel = [[UILabel alloc] initWithFrame:rect];
bodyLabel.font = [UIFont fontWithName:#"HelveticaNeue" size:12];
bodyLabel.numberOfLines = 5;
bodyLabel.lineBreakMode = UILineBreakModeWordWrap;
bodyLabel.textColor = [UIColor blackColor];
[self.contentView addSubview: bodyLabel];

The documentation for -drawAtPoint:withFont:... says "This method does not perform any line wrapping during drawing." If you use -drawInRect:withFont: instead of -drawAtPoint:withFont:..., then it will draw multiple lines. You can also use -sizeWithFont:constrainedToSize: to figure out what the size will be.

Instead of deprecated drawInRect:withFont:... in iOS7+ you should use drawWithRect:options:attributes:context:
[string drawWithRect:CGRectMake(x, y, width, height)
options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine
attributes:#{NSFontAttributeName:<font>, NSForegroundColorAttributeName:<color>
context:nil];

Related

Sizing UITextView to its content isn't working

Here's the code for a UITextView that I want to size to the height of its content.
If I write the textView.frame height explicitly like:
textView.frame = CGRectMake(100, 12, 320, 458);
the textView sizes to it's content as expected.
If, however, I write it like the following. It doesn't even display although the NSLog statement says that there's a value to textView.contentSize.height
UITextView *textView = [[UITextView alloc] init];
textView.layer.borderWidth = 5.0f;
textView.layer.borderColor = [[UIColor redColor] CGColor];
textView.text = [item objectForKey:#"description"];
textView.frame = CGRectMake(100, 12, 320, textView.contentSize.height);
NSLog(#"%f textviewcontnet size", textView.contentSize.height);
textView.editable = NO;
[self.view addSubview:textView];
When I log the output of:
NSLog(#"%f textviewcontent size", textView.contentSize.height);
I get "458.000000 textviewcontent size"
thanks for any help
I'd suggest trying:
UITextView *textView = [[UITextView alloc] init];
textView.layer.borderWidth = 5.0f;
textView.layer.borderColor = [[UIColor redColor] CGColor];
textView.text = [item objectForKey:#"description"];
textView.frame = CGRectMake(100, 12, 320, 458);
textView.editable = NO;
[self.view addSubview:textView];
textView.frame = CGRectMake(100, 12, 320, textView.contentSize.height);
I've heard that textView.contentSize.height doesn't work until it's been added to a view (though that's not my experience). More importantly, I don't know how it would interpret textView.contentSize.height if it doesn't yet know what the width of the control is. So go ahead, set the initial frame, do addSubview and then readjust the size based upon textView.contentSize.height.
Quickly copied out of one of my projects:
AppDelegate *appDelegate;
CGSize textSize1, textSize2;
appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
textSize1 = [self.subjectLabel.text sizeWithFont:[appDelegate fontNormal] constrainedToSize:CGSizeMake(300.0f, 10000.0f) lineBreakMode:NSLineBreakByWordWrapping];
self.subjectLabel.frame = CGRectMake(10, 5, 300, textSize1.height);
textSize2 = [self.descriptionLabel.text sizeWithFont:[appDelegate fontNormal] constrainedToSize:CGSizeMake(300.0f, 10000.0f) lineBreakMode:NSLineBreakByWordWrapping];
self.descriptionLabel.frame = CGRectMake(10, 5 + textSize1.height + 5, 300, textSize2.height);
[appDelegate fontNormal] just returns a UIFont object, the one that I am using for all "normal" text items. Don't worry about that too much. But it is important that you use the same font that is used for the text view too.
My example is a bit easier because it is a UILable. That works with a text view too but you will have to consider the insects. Easy solution, just substract some "fuzzy offset" from the width compared to the frame width of your text view.

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.

sizeWithFont:constrainedToSize:lineBreakMode: not accurate?

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.

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;
}