Get the exact size of UITextView with sizeWithAttribute - ios

I have a UISlider that changes the font size of a UITextView. Before changing the font size, I would like to check if the height of my UITextView will be inferior to the height of its view container. The problem is that sizeToFit and sizeWithAttribute are returning different heights for the same font size.
To do that i'm trying to get the height of my UITextView with a custom fontSize, but i cannot figure out a way to do so, and don't understand why I don't get the same height when I do:
self.photoDescription.text = #"Test"
self.photoDescription.font = [self.photoDescription.font fontWithSize:18];
[self.photoDescription sizeToFit];
NSLog(#"real height %f", self.photoDescription.frame.size.height);
//getting : 37.5
and:
NSLog(#"calculated height %f", [self.photoDescription.text sizeWithAttributes:#{NSFontAttributeName:[self.photoDescription.font fontWithSize:18]}].height);
//getting: 20.97
same thing for:
CGRect textRect = [self.photoDescription.text boundingRectWithSize:CGSizeMake(320, 300)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:[self.photoDescription.font fontWithSize:18]}
context:nil];
CGSize size = textRect.size;
NSLog(#"height %f", size.height);
// getting : 20.97
Any thoughts on this?

I finally found an answer to my question with Jordan Montel Solution:
iOS7 UITextView contentsize.height alternative
I used his function to get the width :
- (CGFloat)textViewHeightForAttributedText:(NSAttributedString *)text andWidth:(CGFloat)width
{
UITextView *textView = [[UITextView alloc] init];
[textView setAttributedText:text];
CGSize size = [textView sizeThatFits:CGSizeMake(width, FLT_MAX)];
return size.height;
}

Related

How to get a height a UITextView should be given width and length of text?

I am adding a UIView that contains a UITextView which is constrained to the top, left, and bottom of the view.
The width of the UIView should be the screen size's width which in turn will be the UITextView's width.
When I go to create this UIView, I can make it's CGSize to the screen size's width, but I am not sure on how to calculate the height.
How can I figure out what height I must set this UIView so that the UITextView can properly show? Is there a way I can figure out the number of lines a UITextView would have given a certain width?
You can use the following code to Get a dynamic Rect:
NSString *myDynamicString = #"Hello World!";
CGSize textRect = [myDynamicString boundingRectWithSize:CGSizeMake(MAX_WIDTH, MAX_HEIGHT)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:[UIFont fontWithName:#"YouFontName" size:15]}
context:nil];
Note
MAX_WIDTH Width allowed to expand the rect. If you give 200 then the rect will exapand till 200 and then break and Vice Versa for MAX_HEIGHT
Use this code
CGSize constraintSize = CGSizeMake(textView.width - 2*textView.textContainer.lineFragmentPadding, CGFLOAT_MAX);
CGFloat messageTextViewHeight = [text boundingRectWithSize:constraintSize
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName: textView.font}
context:nil].size.height;
-(CGSize)getSizeForText:(NSString *)text maxWidth:(CGFloat)width font:(NSString *)fontName fontSize:(float)fontSize
{
CGSize constraintSize;
constraintSize.height = MAXFLOAT;
constraintSize.width = width;
NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
[UIFont fontWithName:fontName size:fontSize], NSFontAttributeName,
nil];
CGRect frame = [text boundingRectWithSize:constraintSize
options:NSStringDrawingUsesLineFragmentOrigin
attributes:attributesDictionary
context:nil];
CGSize stringSize = frame.size;
return stringSize;
}
First of all if you are using auto-layout this will be done out of the box, you don't have to do anything just setup constraints of auto-layout properly.
NSSString API is not very handy (as you can see in other answers) it is easy to miss something. I prfer use -(CGSize)sizeThatFits: from UIView.
UIView *textView = self.textView;
CGSize fitSize = { CGRectGetWidth(textView.frame), CGFLOAT_MAX };
CGSize fitSize = [textView sizeThatFits: fitSize];
NSLog(#"Your desired height: %f", fitSize.height);
It is more reliable and it should take into account all properties of text inside UITextView. I used this for UILabel didn't test for UITextView but it should work nicely.
If you want to see all the text in the text view an have the surrounding views around it adapt to contain it the easiest way would be to use a UILabel instead. Then you could just use constraints with priorities. Set the UILabel number of lines to 0 so that it automatically wraps. Then set the contentCompressionResistancePriority to 1000 for vertical axis. Then you don't need to worry about the sizes. Let autolayout do the work for you.

How to change the frame of textview as content changes?

Is it possible to change both width and height of the textview with respect to content. Here, the height of the text only varies when user enters an new line character.
How to do pinch zoom on textview, such that font doesn't look blur. It needs to be work on from iOS5.
Try this it has worked for me. viewNote is my textView object. it is for height
CGRect frame = viewNote.frame;
NSLog(#"Text Size height : %f",frame.size.height);
CGSize textViewSize;
if (isIPhone) {
textViewSize = [viewNote.text sizeWithFont:[UIFont fontWithName:#"Helvetica" size:20]
constrainedToSize:CGSizeMake(309, 10000)
lineBreakMode:UILineBreakModeTailTruncation];
}else{
textViewSize = [viewNote.text sizeWithFont:[UIFont fontWithName:#"Helvetica" size:30]
constrainedToSize:CGSizeMake(768, 10000)
lineBreakMode:UILineBreakModeTailTruncation];
}
frame.size.height = textViewSize.height;
viewNote.frame = frame;
NSLog(#"Text Size height : %f",frame.size.height);

Manage label text dynamically not work properly

CGFloat constrainedSize = 500.0f;
UIFont * myFont = [UIFont fontWithName:#"Arial" size:19]; //or any other font that matches what you will use in the UILabel
CGSize textSize = [myText sizeWithFont: myFont
constrainedToSize:CGSizeMake(constrainedSize, CGFLOAT_MAX)
lineBreakMode:NSLineBreakByWordWrapping];
lblDescription=[[UILabel alloc]initWithFrame:CGRectMake(10,y, 300,textSize.height)];
i have tried this code for manage the dynamic text. but if the data comes larger it will not display the whole text.
You constrain the size to width = 500pt, but your textfield is only 300pt wide.
Edit:
It seems, I wasn't clear. If you calculate the height of the label with sizeWithFont and give as constraint a width of 500pt (constrainedSize) and use the calculated height then on a label with only 300pt width, the calculated height is not correct.
This is how it works for me:
CGFloat constrainedSize = 300.0f;
UIFont * myFont = [UIFont fontWithName:#"Arial" size:19]; //or any other font that matches what you will use in the UILabel
CGSize textSize = [myText sizeWithFont: myFont
constrainedToSize:CGSizeMake(constrainedSize, CGFLOAT_MAX)
lineBreakMode:NSLineBreakByWordWrapping];
UILabel* lblDescription=[[UILabel alloc]initWithFrame:CGRectMake(10.0, 10.0, constrainedSize, textSize.height)];
lblDescription.lineBreakMode = NSLineBreakByWordWrapping;
lblDescription.numberOfLines = 0;
lblDescription.font = myFont;
lblDescription.text = myText;
Again: use the same attributes for the label (font, size, lineBreakMode) as you use for the calculation, otherwise it won't fit.
That's because you are alloc and initing the UILabel, and never reset it's frame for bigger size text.
Simply set the frame of the UILabel after a text size change.
This line sets the size of the label, to textSize.height and it doesn't change.
lblDescription=[[UILabel alloc]initWithFrame:CGRectMake(10,y, 300,textSize.height)];
You can call setFrame to programmatically change this.
To display a larger text/Multiline text you should use UITextView instead. It is designed to handle this issue.
hi here is code to set dynamic text in label
CGSize maximumLabelSize = CGSizeMake(300,9999);
CGSize expectedLabelSize = [label.text sizeWithFont:label.font
constrainedToSize:maximumLabelSize
lineBreakMode:label.lineBreakMode];
CGRect newFrame = label.frame;
newFrame.size.height = expectedLabelSize.height;
label.frame = newFrame;
i hope this is helping to you..

UILabel text alignment issues in iphone?

I am getting JSON response from server and set that contents to UILabel and sometimes the text will be one line and sometimes the text will be 10 lines.So i display this UILabel inside the UIScrollView. But i got the empty space in UILabel
This is my screenshots..
Currently i am using storyboard and auto layout
So i want to avoid these empty space in UILabel. Please give me suggestions for this alignment issues.??
Code for changing UILabel height but this is not working for me
CGRect textRect = [strDetailsFinal boundingRectWithSize:CGSizeMake(296, FLT_MAX)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName: labDetails.font}
context:nil];
CGSize size = textRect.size;
CGRect newFrame = labDetails.frame;
newFrame.size.height = size.height;
labDetails.frame = CGRectMake(160, 200, 300, newFrame.size.height);
May this help you
NSDictionary *attributesDic= [NSDictionary dictionaryWithObjectsAndKeys:
[UIFont fontWithName:#"FontName" size:15], NSFontAttributeName,nil];
CGRect frame = [label.text boundingRectWithSize:CGSizeMake(263, 2000.0)
options:NSStringDrawingUsesLineFragmentOrigin attributes:attributesDic context:nil];
CGSize size = frame.size;
and its possible answer Dynamically resize label in iOS 7 or you can try this https://gist.github.com/danielphillips/1005520
Use [labDetails sizeToFit]. If you have size constraints then use [sizeThatFits:CGSizeMake(WidthConstraint, HeightConstraint)] then use the result of that to set your label frame.
why don't you use UIButton instead of UILabel. UIButton has property to align the text vertically, while UILabel doesn't.
Use UIButton with userInteractionEnabled = NO. Check my this reply here: Vertically align UILabel
Remember one thumb rule - You should not set frame when using autolayout - You are going against Autolayout basic concept - Instead try to autolayout constraints programatically in your case
-(void)awakeFromNib{
[super awakeFromNib];
for(NSLayoutConstraint *cellConstraint in self.constraints){
[self removeConstraint:cellConstraint];
id firstItem = cellConstraint.firstItem == self ? self.contentView : cellConstraint.firstItem;
id seccondItem = cellConstraint.secondItem == self ? self.contentView : cellConstraint.secondItem;
NSLayoutConstraint* contentViewConstraint =
[NSLayoutConstraint constraintWithItem:firstItem
attribute:cellConstraint.firstAttribute
relatedBy:cellConstraint.relation
toItem:seccondItem
attribute:cellConstraint.secondAttribute
multiplier:cellConstraint.multiplier
constant:cellConstraint.constant];
[self.contentView addConstraint:contentViewConstraint];
}
}
You have taken a fix size UILable rather you have to use a dynamic size UILable.
Before that you need to calculate the size of text/string
#define FONT_SIZE 15.0f
#define LABEL_CONTENT_WIDTH 320.0f
#define LABEL_CONTENT_MARGIN 10.0f
NSString *text = #"YOUR TEXT HERE";
CGSize constraint = CGSizeMake(LABEL_CONTENT_WIDTH - (LABEL_CONTENT_MARGIN * 2), 20000.0f);
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:NSLineBreakByWordWrapping];
CGFloat height = MAX(size.height, 44.0f);
after calculating the size, apply them to your label like below
[labDetails setFrame:CGRectMake(labDetails.frame.origin.x, labDetails.frame.origin.y, labDetails.frame.size.width, MAX(height, 44.0f))];
And If you are using autolayout option then please check here: Link
Use Upper label frame's origin and size, and based on that set your detail labels frame, Use sizeToFit property of label.
Suppose 582,618 is your title label,
Like,
labDetails.frame=CGRectMake(5, title.frame.origin.x+title.frame.size.height+5, 300, 100);
[labDetails sizeToFit];

UITextView with dynamically height

I have a textView which insert different texts with different lengths, some are short and others are long.. The UITextView is subviews of a scrollView. How can I dynamically set the height of UITextView according to the length of the entered text?
This code in ViewDidLoad doesn't work:
self.textView.contentSize = [self.textView.text sizeWithFont:[UIFont systemFontOfSize:14] constrainedToSize:CGSizeMake(100, self.textView.contentSize.height) lineBreakMode:UIViewAutoresizingFlexibleHeight];
This does not work because your contraint is the current contentSize of the TextView. You should put the maximum size that you want.
For example your code could be like this :
#define kMaxHeight 100.f
self.textView.contentSize = [self.textView.text sizeWithFont:[UIFont systemFontOfSize:14]
constrainedToSize:CGSizeMake(100, kMaxHeight)
lineBreakMode:UIViewAutoresizingFlexibleHeight];
Hope this helps
As UITextView is a subclass of UIScrollView , so may be this will be helpful:
UITextView *textView = [UITextView new];
textView.text = #"Your texts ......";
CGSize contentSize = textView.contentSize ;
CGRect frame = textView.frame ;
frame.size.height = contentSize.height ;
textView.frame = frame ;
Below coding is working.Please try it
// leave the width at 300 otherwise the height wont measure correctly
UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(10.0f, 0.0f, 300.0f, 100.0f)];
// add text to the UITextView first so we know what size to make it
textView.text = [_dictSelected objectForKey:#"body"];
// get the size of the UITextView based on what it would be with the text
CGFloat fixedWidth = textView.frame.size.width;
CGSize newSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
CGRect newFrame = textView.frame;
newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
textView.frame = newFrame;
Calculate string size that fits in UITextView:
[yourString sizeWithFont:yourtxtView.font
constrainedToSize:CGSizeMake(yourtxtView.frame.size.width,1000)
lineBreakMode:UILineBreakModeWordWrap];
Change frame of UITextView
yourtxtView.frame = CGRectMake(yourtxtView.frame.origin.x,yourtxtView.frame.origin.y,yourtxtView.frame.size.width,yourtxtView.frame.size.height+20);

Resources