iOS: How can I achieve design with dynamic length text? - ios

How can I make a simple design like in the image below where text length is dynamic? In the image below there are two sections Ingredients and Instructions with dynamic text length. There could be more sections.
Should I go for UIView with a UIScrollView or Table View? Any kind of help would be appreciated.

Try this approach.
1. Use UITextView this will give you possibility to scroll text inside UITextView if text will be very big.
2. Get the size of you text view
// return the size for UITextView for both IOS7 and IOS6
-(CGSize) getSizeWithMaxLabelSize:(CGSize) maxLabelSize forTextViewWithText:(NSString *) text
{
CGSize expectedLabelSize;
CGSize maximumLabelSize = maxLabelSize;
if (SYSTEM_VERSION_GREATER_THAN(#"6.2")) {
NSDictionary *stringAttributes = [NSDictionary dictionaryWithObject:[UIFont fontWithName:#"Arial" size:12] forKey: NSFontAttributeName];
CGRect rect =[text boundingRectWithSize:maximumLabelSize options:NSStringDrawingUsesLineFragmentOrigin attributes:stringAttributes context:nil];
expectedLabelSize = rect.size;
expectedLabelSize.height = ceilf(expectedLabelSize.height);
expectedLabelSize.width = ceilf(expectedLabelSize.width);
} else {
expectedLabelSize = [text sizeWithFont:[UIFont fontWithName:#"Arial" size:EPCommentViewFontSize] constrainedToSize:maximumLabelSize lineBreakMode:NSLineBreakByWordWrapping];
}
return expectedLabelSize;
}
3. Use this method (2) when you calculate cell height for you table
- tableView:cellForRowAtIndexPath:

You should go for UITextView/UILabel with UIScrollView. UILabel is preferable if the content is not editable and you do not need the text scrolling on the fixed area.
If your needs fulfilled by these, you need to go with UILabel with UIScrollView.

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.

UILabel can't get multiples lines on increasing dynamic height of text in iOS 7

I am developing an app, in which I am getting dynamic text and I have to increase height of label dynamically depending upon text and also increase and decrease height of table cell on basis on label height. So I wrote code both for iOS 6 and iOS7 and it works fine in iOS 6 but in iOS7 it not working fine. Below is code. Function that return height of text.
- (CGSize)getSizeOfText:(NSString *)text withFont:(UIFont *)font widthOftext:(int )txtWidth
{
CGSize boundingSize = CGSizeMake(txtWidth, 1000);
CGSize size;
if (MyDelegate.isIos7)
{
NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
font, NSFontAttributeName,
nil];
CGRect frame = [text boundingRectWithSize:boundingSize
options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
attributes:attributesDictionary
context:nil];
return frame.size;
}
else
{
CGSize requiredSize = [text sizeWithFont:font constrainedToSize:boundingSize lineBreakMode:UILineBreakModeWordWrap];
size=requiredSize;
}
return size;
}
There is bit change on return of height for iOS 6 and iOS 7.
Below First four label's text height difference for both them.
iOS6
42.000000
42.000000
21.000000
42.000000
iOS7
39.674072
39.674072
20.123291
39.674072
You can see bit difference of first four texts. But One major problem more in iOS is that It always show me text in just one line and truncate text even text height goes to 39 which may come in 2 lines, I also set number of lines to 20 and also tried to set number line to just 0 but didn't work.
Kindly guide me on this if anyone already this sort of problem. Thanks
Edited
I already posted this question earlier if anyone want to see screen shots of both iOS results so check there also.
Same Thread with Screen Shots
Try to set this property to your label
label.numberOfLines = 3;
it should solve the problem and let me know.
Set the height of the label to frame.size.height+1 or round it up.
and of course make sure the numberOfLines of your label is 3 (or 0 if you think it is possible to show more than 3).
Try in this way for dynamic change of height for cell using UITableView. This works for me for IOS7 and IOS6 also
At -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellText=yourtextstring;
UIFont *cellFont = [UIFont fontWithName:#"SourceSansPro-Bold" size:13.0];
CGSize constraintSize = CGSizeMake(300.0f, MAXFLOAT);//225
CGSize labelSize = [cellText sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:NSLineBreakByWordWrapping];
//NSLog(#"*** labelSize.height *** %f",labelSize.height);
return labelSize.height+250; //change this as per your need
}
At - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellText=yourtextstring;
UIFont *cellFont=[UIFont fontWithName:#"SourceSansPro-Regular" size:13.0];
CGSize constraintSize=CGSizeMake(300,MAXFLOAT);
CGSize txtViewSize=[cellText sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:NSLineBreakByWordWrapping];
CGRect frame=cell.yourlabel.frame;
// frame.size.width=300;
frame.size.height=txtViewSize.height+150;
cell.yourlabel.frame=frame;
cell.yourlabe.text=cellText;
return cell;
}
Hope it helps you..
NO need to compare for iOS 6 and iOS 7
use like below
CGFloat txtWidth = 250.0f;
NSString *font = #"Noteworthy-Bold"; //say u hav font
NSString *text = #"Some long text Some long text Some long text Some long text Some long text Some long text Some long text Some long text Some long text Some long text Some long text Some long text Some long text"; //say u hav some text
UIFont *labelFont = [UIFont fontWithName:font size:15];
NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObject:labelFont forKey:NSFontAttributeName];
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:text attributes:attributesDictionary];
CGRect frame = [attributedText boundingRectWithSize:(CGSize){txtWidth, MAXFLOAT}
options: (NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
context:nil];//you need to specify the some width, height will be calculated
CGSize requiredSize = frame.size;
NSLog(#"wdth->%f height->%f",requiredSize.width,requiredSize.width);
//248.962509 height->248.962509 //iOS 7
//248.962494 height->248.962494 //iOS 6
//almost same
//also set 'numberOfLines` property of label

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..

Table cell height by UITextView where content alignment is NSTextAlignmentJustified

I have a UITextView where content is aligned by NSTextAlignmentJustified. In the cellForRowAtIndexPath: add this text view to cell content view and change frame according it's content by
UITextView *commentsTextView = (UITextView *)[self getCommentField:comment];
[cell.contentView addSubview:commentsTextView];
CGRect tempFrame = commentsTextView.frame;
tempFrame.size.height = commentsTextView.contentSize.height;
commentsTextView.frame = tempFrame;
So far, so good. Now, how to detect contentSize of that view for heightForRowAtIndexPath:?
I tried
NSString *comment = [[self.allComments objectAtIndex:indexPath.row] objectForKey:#"commentText"];
CGSize constraintSize = CGSizeMake(315.0f, MAXFLOAT);
CGSize size = [comment sizeWithFont:[UIFont systemFontOfSize:14.0]
constrainedToSize:constraintSize
lineBreakMode:NSTextAlignmentJustified];
Also I tried lineBreakMode:NSLineBreakByWordWrapping and so. But cell height is always smaller when text is long, because there seems to be no way how to coumpute size of justified text (because of the white spaces in the middle of text). Font is same.
OK, i got it. UITextView has 8 pixels insect from each side, co my CGSizeMake(315.0f, MAXFLOAT); have to be CGSizeMake(299.0f, MAXFLOAT);

Resize UITableViewCell to UILabel's height dynamically

I want to resize cell's height according to the label's height and label's height according to text. Or is there any way I can resize the cell's height according to the text entered in UITextView?
THIS METHOD IS DEPRECATED SINCE iOS 7.0.
There is a UITableView delegate method called heightForRowAtIndexPath that is called before you create a cell or a table.
You could use the NSIndexPath passed to it to get the text at a specific row and use the sizeWithFont method from UIStringDrawing.h to compute a CGSize for that row.
For example:
CGSize size = [text sizeWithFont:font
constrainedToSize:maximumLabelSize
lineBreakMode:UILineBreakModeWordWrap];
And finally you would return size.height.
--For iOS7--
Basing this off of Josh Vera's answer … place this in heightForRowAtIndexPath.
I have my table data stored in an NSArray *tableData.
// set the desired width of the textbox that will be holding the adjusted text, (for clarity only, set as property or ivar)
CGFloat widthOfMyTexbox = 250.0;
-(float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
//Get a reference to your string to base the cell size on.
NSString *cellText = [self.tableData objectAtIndex:indexPath.row];
//set the desired size of your textbox
CGSize constraint = CGSizeMake(widthOfMyTextBox, MAXFLOAT);
//set your text attribute dictionary
NSDictionary *attributes = [NSDictionary dictionaryWithObject:[UIFont systemFontOfSize:14.0] forKey:NSFontAttributeName];
//get the size of the text box
CGRect textsize = [cellText boundingRectWithSize:constraint options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil];
//calculate your size
float textHeight = textsize.size.height +20;
//I have mine set for a minimum size
textHeight = (textHeight < 50.0) ? 50.0 : textHeight;
return textHeight;
}
I haven't tested it for iOS<7, but I believe it should work for that as well.

Resources