Drawing text in UITableViewCell - iphone

I used the following method to draw text in my custome cell, it's working fine but I just found that part of the text missing(Not showing all text in the cell):
- (void)drawContentView:(CGRect)rect {
UIColor * textColor = [UIColor blackColor];
if (self.selected || self.highlighted){
textColor = [UIColor whiteColor];
}
else
{
[[UIColor whiteColor] set];
UIRectFill(self.bounds);
}
[textColor set];
UIFont * textFont = [UIFont systemFontOfSize:16];
CGSize textSize = [text sizeWithFont:textFont constrainedToSize:rect.size];
[text drawInRect:CGRectMake(self.frame.size.width-(textSize.width+2 ) ,
(rect.size.height / 2) - (textSize.height / 2),
textSize.width, textSize.height) withFont:textFont lineBreakMode:NSLineBreakByWordWrapping alignment:NSTextAlignmentRight];
}
Thanks, please advice.

Try to make the space for drawing bigger than the textSize.width, textSize.heigh
UIFont * textFont = [UIFont systemFontOfSize:16];
CGSize sizeMe = CGSizeMake(300, rect.size.height*1.5);
CGSize textSize = [text sizeWithFont:textFont constrainedToSize:sizeMe];
[text drawInRect:CGRectMake(self.frame.size.width-(textSize.width+10 ) ,
(rect.size.height / 2) - (textSize.height / 2),
textSize.width, textSize.height+(textSize.height*1.5)) withFont:textFont lineBreakMode:NSLineBreakByWordWrapping alignment:NSTextAlignmentRight];

Perhaps you should change the line that determines text size to:
CGSize textSize = [text sizeWithFont:textFont constrainedToSize:rect.size lineBreakMode: NSLineBreakByWordWrapping];

You did not consider the lineBreakMode in sizeWithFont. You may want to use – sizeWithFont:constrainedToSize:lineBreakMode: instead for determine the actual size.
BTW, when your constraint is exactly the rect.size then the return value will never be larger than the actual rect.size. That may be what you want. Whenever I deal with strings of variable length in custom cells, I like to know whether the string fits in or not and may enlarge the individual cell (which requieres some more work of course).
If you do that then set the size.height of the constraints size to something very high. 10000.0f or so.

You are creating a custom cell .What is the need for drawing the text into it?That is the purpose of Label just add as the subview and use it.
drawInRect is a coregraphics drawing method
as per docs
Draws the string in the current graphics context using the specified
bounding rectangle and font. This method draws as much of the string
as possible using the given font and constraints. This method uses the
UILineBreakModeWordWrap line break mode and the UITextAlignmentLeft
alignment.
I dont see you get the context before drawing .Hence it doesnot have a valid context.and hence not drawing

Related

iPhone - Adjust UILabel width according to the text

How can I adjust the label Width according to the text? If text length is small I want the label width small...If text length is small I want the label width according to that text length. Is it possible?
Actually I have Two UIlabels. I need to place these two nearby. But if the first label's text is too small there will be a big gap. I want to remove this gap.
//use this for custom font
CGFloat width = [label.text sizeWithFont:[UIFont fontWithName:#"ChaparralPro-Bold" size:40 ]].width;
//use this for system font
CGFloat width = [label.text sizeWithFont:[UIFont systemFontOfSize:40 ]].width;
label.frame = CGRectMake(point.x, point.y, width,height);
//point.x, point.y -> origin for label;
//height -> your label height;
Function sizeWithFont: is deprecated in iOS 7.0, so you have to use sizeWithAttributes: for iOS 7.0+. Also to suport older versions, this code below can be used:
CGFloat width;
if ([[UIDevice currentDevice].systemVersion floatValue] < 7.0)
{
width = [text sizeWithFont:[UIFont fontWithName:#"Helvetica" size:16.0 ]].width;
}
else
{
width = ceil([text sizeWithAttributes:#{NSFontAttributeName: [UIFont fontWithName:#"Helvetica" size:16.0]}].width);
}
Using function ceil() on result of sizeWithAttributes: is recommended by Apple documentation:
"This method returns fractional sizes; to use a returned size to size views, you must raise its value to the nearest higher integer using the ceil function."
sizeWithAttributes
// In swift 2.0
let lblDescription = UILabel(frame: CGRectMake(0, 0, 200, 20))
lblDescription.numberOfLines = 0
lblDescription.text = "Sample text to show its whatever may be"
lblDescription.sizeToFit()
// Its automatically Adjust the height
Try these options,
UIFont *myFont = [UIFont boldSystemFontOfSize:15.0];
// Get the width of a string ...
CGSize size = [#"Some string here" sizeWithFont:myFont];
// Get the width of a string when wrapping within a particular width
NSString *mystring = #"some strings some string some strings...";
CGSize size = [mystring sizeWithFont:myFont
forWidth:150.0
lineBreakMode:UILineBreakModeWordWrap];
You can also try with [label sizeToFit]; Using this method, you can set frame of two labels as,
[firstLabel sizeToFit];
[secondLabel sizeToFit];
secondLabel.frame = CGRectMake(CGRectGetMaxX(firstLabel.frame), secondLabel.origin.y, secondLabel.frame.size.width, secondLabel.frame.size.height);
sizeWithFont constrainedToSize:lineBreakMode: is the original method to use. Here is an example of how to use it is below:
//Calculate the expected size based on the font and linebreak mode of your label
CGSize maximumLabelSize = CGSizeMake(296,9999);
CGSize expectedLabelSize = [yourString sizeWithFont:yourLabel.font constrainedToSize:maximumLabelSize lineBreakMode:yourLabel.lineBreakMode];
//adjust the label the the new height.
CGRect newFrame = yourLabel.frame;
newFrame.size.height = expectedLabelSize.height;
yourLabel.frame = newFrame;
just use to if you using constrain in your view or xib or cell
[LBl sizeToFit];
if its not working then
dispatch_async(dispatch_get_main_queue(), ^{
[LBl sizeToFit];
});
Try the following:
/* Consider these two labels as the labels that you use,
and that these labels have been initialized */
UILabel* firstLabel;
UILabel* secondLabel;
CGSize labelSize = [firstLabel.text sizeWithFont:[UIFont systemFontOfSize:12]];
//change the font size, or font as per your requirements
CGRect firstLabelRect = firstLabel.frame;
firstLabelRect.size.width = labelSize.width;
//You will get the width as per the text in label
firstLabel.frame = firstLabelRect;
/* Now, let's change the frame for the second label */
CGRect secondLabelRect;
CGFloat x = firstLabelRect.origin.x;
CGFloat y = firstLabelRect.origin.y;
x = x + labelSize.width + 20; //There are some changes here.
secondLabelRect = secondLabel.frame;
secondLabelRect.origin.x = x;
secondLabelRect.origin.y = y;
secondLabel.frame = secondLabelRect;

UILabel size to fit

I have a problem involving UILabel's sizeToFit method:
UILabel *questionLabel = [[UILabel alloc]initWithFrame:CGRectMake(0,0,320,320)];
questionLabel.lineBreakMode = UILineBreakModeWordWrap;
questionLabel.backgroundColor=[UIColor clearColor];
questionLabel.textAlignment=UITextAlignmentLeft;
questionLabel.textColor=[UIColor blackColor];
questionLabel.tag=1;
questionLabel.font=[UIFont systemFontOfSize:13];
questionLabel.numberOfLines = 0;
[questionLabel sizeToFit];
[myView addSubview:questionLabel];
I had written this code for displaying my data. But if I write: [questionLabel sizeToFit] my data does not display properly. If I remove [questionLabel sizeToFit] then it is displaying but it only shows half the data.
Thanks and Regards.
NSString *yourString = #"write your label text here";
CGSize s = [yourString sizeWithFont:[UIFont systemFontOfSize:12] constrainedToSize:CGSizeMake(width, MAXFLOAT) lineBreakMode:UILineBreakModeWordWrap];
questionLabel.frame = CGRectMake(0, 0, s.width, s.height);
Check if it helps.
I think it's best to use taus-iDeveloper answer to compute the size of a label.
I just want to say that the reason your code is not working is because you didn't set text to your UILabel so sizeToFit returns CGSizeZero (so it doesn't appear on screen). You have to set text before using sizeToFit.
I found that if AutoLayout is on then size to fit not work
i googled d above problem and came across some info that sizeToFit seems to be a bug and it has been reported to apple already.
So as a workaround u can use this code:
NSString * myText = [NSString stringWithString:#"some text"];
CGFloat constrainedSize = 265.0f;
UIFont * myFont = [UIFont fontWithName:#"Arial" size:19];
CGSize textSize = [myText sizeWithFont: myFont
constrainedToSize:CGSizeMake(constrainedSize, CGFLOAT_MAX)
lineBreakMode:UILineBreakModeWordWrap];
CGRect labelFrame = CGRectMake (0, 0, textSize.width, textSize.height);
UILabel *label = [[UILabel alloc] initWithFrame:labelFrame];
[label setFont:myFont];
[label setText:myText];
I've found that when using sizeToFit with a UILabel, in InterfaceBuilder you need to change the Autoshrink property from 'Fixed Font Size' to 'Minimum Font Size'. I usually then set its value to 0.5 to be sure its working properly.
just make sure you increase the number of lines of the label. Instead of
questionLable.numberOfLines = 0; make use of
questionLable.numberOfLines = 4;
As it will force the system to compute the smallest width possible for 4 lines.
You can achieve this via the Xib file too..

Multiline text (wordwrap) with drawAtPoint?

is there a way to draw multiline text with drawAtPoint?
I have tried UILineBreakModeWordWrap but doesnt seem to be working?
How would you convert this code to a working multiline text??
point = CGPointMake(boundsX, 50);
[self.heading drawAtPoint:point forWidth:labelWidth withFont:mainFont minFontSize:12.0 actualFontSize:NULL lineBreakMode:UILineBreakModeWordWrap baselineAdjustment:UIBaselineAdjustmentAlignBaselines];
Thank you!
drawAtPoint: doesn't support multiline text. You can use drawInRect: method instead.
Edit: (Copying #George Asda's comment below to here)
[self.heading drawInRect:(contentRect) withFont:mainFont
lineBreakMode:UILineBreakModeWordWrap alignment:UITextAlignmentCenter];
[_text drawWithRect:_textRect options:**NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine** attributes:attributes context:nil];
This cannot be done with the NSString drawAtPoint method. From the documentation:
Draws the string in a single line at the specified point in the
current graphics context using the specified font and attributes.
Could you perhaps use a simple UILabel?
EDIT
You can calculate the height of a UILabel like this:
//Calculate the expected size based on the font and linebreak mode of your label
CGSize maximumLabelSize = CGSizeMake(296,9999);
CGSize expectedLabelSize = [yourString sizeWithFont:yourLabel.font
constrainedToSize:maximumLabelSize
lineBreakMode:yourLabel.lineBreakMode];
//adjust the label the the new height.
CGRect newFrame = yourLabel.frame;
newFrame.size.height = expectedLabelSize.height;
yourLabel.frame = newFrame;

How to adjust and make the width of a UILabel to fit the text size?

In my project, there is a UILabel with text. The font size is 16pt. The text contents are changed depending on different cases. I hope it can automatically adjust the width of UILabel to fit the total width of texts without stretching.
Is it possible?
This assumes you have already set the font:
label.text = #"some text";
[label sizeToFit];
You will also need to define a maximum width, and tell your program what to do if sizeToFit gives you a width greater than that maximum.
Here's how to do it, suppose the following messageLabel is the label you want to have the desired effect. Now, try these simple line of codes:
// Set width constraint for label; it's actually the width of your UILabel
CGFloat constrainedWidth = 240.0f;
// Calculate space for the specified string
CGSize sizeOfText = [yourText sizeWithFont:yourFont constrainedToSize:CGSizeMake(constrainedWidth, CGFLOAT_MAX) lineBreakMode:UILineBreakModeWordWrap];
UILabel *messageLabel = [[UILabel alloc] initWithFrame:CGRectMake(20,20,constrainedWidth,sizeOfText.height)];
messageLabel.text = yourText;
messageLabel.numberOfLines = 0;// This will make the label multiline
NSString *txt1=#"I am here.";
CGSize stringsize1 = [txt1 sizeWithFont:[UIFont systemFontOfSize:14]];
[label setFrame:CGRectMake(x,y,stringsize1.width,hieght)];
[label setText:txt1];
I see three options here.
First, make label's size big enough to hold any text. That's most simple, but does not always work well - depends on its surrounding views.
Second, Label can adapt size of the font for longer text (adjustsFontSizeToFitWidth property). This is often not desirable, different fonts in elements might look ugly.
Last option is to programmatically resize the label according to its currently holding text. To calculate the size required to hold the text with current font use something like this:
CGSize textSize = [[someLabel text] sizeWithFont:[someLabel font] forWidth:someLabel.bounds.size.width lineBreakMode:UILineBreakModeWordWrap];
If you set your font and its size already and if you have your frame defined, try using the following for these two common conditions:
if (label.text.length > maxCharPerLine) [label setNumberOfLines:0]; // infinite lines
else [label setNumberOfLines:1]; // one line only
// Adjust your font size to fit your desired width.
[label setAdjustsFontSizeToFitWidth:YES];
Using Auto Layout:
In the ViewController:
override func viewDidLoad() {
super.viewDidLoad()
sampleLabel.text = "Electrical Maintenance and Repair"
sampleLabel.sizeToFit()
}
As sizeWithFont is depreciated in IOS 7.0 then you below code
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
if (SYSTEM_VERSION_LESS_THAN(#"7.0")) {
// code here for iOS 5.0,6.0 and so on
CGSize fontSize = [itemCat_text sizeWithFont:[UIFont fontWithName:#"Helvetica" size:12]];
} else {
// code here for iOS 7.0
fontSize = [itemCat_text sizeWithAttributes:
#{NSFontAttributeName:
[UIFont fontWithName:#"Helvetica" size:12]}];
}
Follow this.
CGSize stringsize = [yourString sizeWithFont:[UIFont systemFontOfSize:fontSize]];
[label setFrame:CGRectMake(x,y,stringsize.width,height)];
[label setText: yourString];

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.