UITextView text cut off when there is a large amount of text - ios

I have a UITableViewCell subclass that contains a UITextView where scrolling is turned off. I set its frame like this, in my table view cell layoutSubviews method:
CGRect frame = self.bodyTextView.frame;
CGSize size = self.bodyTextView.contentSize;
frame.size = size;
self.bodyTextView.frame = frame;
This has been working fine for some time, but I've noticed that in a case where I have a particularly large amount of text, the text is getting cut off. I've set the text view frame background color to orange so I could verify that the frame was being set correctly. Here is an example (I am only showing the bottom portion of the text view):
The frame is the correct size based on the text (in this case 1019 points), but the text stops before the bottom of the text view. I have also seen the text get cut off part way through a line, (ie the text of the last visible line of text is cut off half way through horizontally). Does anyone have an idea what is happening here?
A few other points:
The text views work well for all my table view cells with shorter content.
If I increase the amount of text in the case shown above, the text view height increases, but the text still gets cut off at the same place.

According to this and similar answers, the problem could be that "the correct contentSize is only available after the UITextView has been added to the view ... Prior to that it is equal to frame.size"
I'd suggest you to calculate the height in a different way, like -sizeWithFont: or -sizeTofit

Use this to get the textSize
// find the text width; so that btn width can be calculate
CGSize textSize = [#"YOUR TEXT" sizeWithFont:[UIFont fontWithName:#"Arial" size:20.0]
constrainedToSize:CGSizeMake(320.0f, 99999.0f)
lineBreakMode:UILineBreakModeWordWrap];
and then set height using this as :
CGRect frame = self.bodyTextView.frame;
frame.size = textSize;
self.bodyTextView.frame = frame;
Hope it helps you.

I had the same issue and resolved it working on the textView padding (in swift5):
yourTextView.textContainerInset = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
Hope it can help :)

Related

How to break line of a UILabel dynamically with text?

I have a UILabel and I want to show some text in this label. I want to increase the label width at most 70% of the full screen of my device. If text length of that label doesn't fit this 70% of size then the label automatically goes to the next line as long as the text length. Every time the label length cross the 70% width of main screen then lines break as well. I have tried several ways but unable to solve yet. Please help me to solve this.
Thanks in advance;
Drag a label to your storyboard and add top and leading constraints to it.
Now select the label and control drag to the view holding the label (in your case view of ViewController) you will see the pop up and then select equal width
Now your Label's width is equal to your view's width :) That's not you want you want ur label width to be 70% of your view. So select the equal constraint of label, go to property inspector and change the multiplier to 0.7
Now your label width is 70% of your view!
But you don't want it to be 70% always. It can be at max 70% of screen, so
now change the relationship of constraint from being equal to less than or equal to.
select label and change number of lines to 0.
That's it :) have fun :)
Sample O/P:
When text is short - vs - long:
- - -
EDIT:
Not using a storyboard? Not a problem; write the same constraint programmatically and apply it to label simple enough. If you need help lemme know :)
EDIT:
As you have specified that you want to leave the gap at the beginning of each line in label you can achieve it by using Edge insets
- (void)drawTextInRect:(CGRect)rect {
UIEdgeInsets insets = {0, 5, 0, 0};
[super drawTextInRect:UIEdgeInsetsInsetRect(rect, insets)];
}
You must have forgotten to increase the label's height.
The code below is for allowing the UILabel to have multiple lines:
label.numberOfLines = 0;
label.lineBreakMode = NSLineBreakByWordWrapping;
Then you have to make sure the UILabel's frame has enough height to show the lines. You can achieve this by calculating the required height for the given text (NSString):
NSString *text = #"YourText";
CGFloat your70Width; // whatever your width is
CGSize constraintSize = CGSizeMake(your70Width, MAXFLOAT);
UIFont *yourLabelFont; // whatever your font is
CGRect requiredFrame = [text boundingRectWithSize:constraintSize options:NSStringDrawingUsesFontLeading attributes:#{NSFontAttributeName:yourLabelFont} context:nil];
// Keeps the old x,y coordinates and replaces only the width and height.
CGRect oldLabelFrame = label.frame;
label.frame = CGRectMake(oldLabelFrame.origin.x, oldLabelFrame.origin.y, requiredFrame.size.width, requiredFrame.size.height);
Now the label will be shown nicely in multiple lines.
To increase the height of the label according to the content if you are using storyboard. Give the label FOUR constraints (Top, Bottom, Leading, Trailing) then go to Attribute Inspector and make lines to 0 and in line break do it WORD WRAP.

Dynamically resize label based on lines of text

I am finding it surprisingly hard to resize a label containing newlines based on the quantity of lines and text. It displays fine in a large enough textview. However, I'd like the economy of sizing the label--or I'd be happy with resizing a textview--exactly.
This is the code I am using from an answer on SO but it is having no effect on the size of the label. Would appreciate any suggestions on how to make this work:
NSString *list = self.list.list;
// use font information from the UILabel to calculate the size
UITextView *view=[[UITextView alloc] initWithFrame:CGRectMake(0, 0, 280, 10)];
//make random size view
view.text=list;
CGSize size=[view sizeThatFits:CGSizeMake(280, CGFLOAT_MAX)];
// create a frame that is filled with the UILabel frame data
CGRect newFrame = _listLabel.frame;
// resizing the frame to calculated size
newFrame.size.height = size.height;
// put calculated frame into UILabel frame
_listLabel.frame = newFrame;
Why are you setting the frame of your label with reference of a newly created UITextView, it will create a useless object in your memory, to set the label frame according to your text just use this 2 line of code
lbl.numberOfLines=0;
[lbl sizeToFit];
It will make the label as large as your text.
You really should use autolayout.
Just constrain the label where you need and let UIKit do it's job.
Here an example:
I set a top space and a leading margin constraints
Then I added a width constraint and then I added some more text
As you can see the label resized itself as it knows how much text it has inside and how much space it occupies.

Changing textView height depending of text it contain

i have detail view controller that shows up after user click on cell, it contain UIImageView, textview that have some text. Sometimes it have several rows of text, sometimes a lot of text. What i want to, is change textView frame height dynamically, depending of amount of text it contain.
That is what i have tried:
-(void)configureTextView{
CGRect frame = self.myTextView.frame;
frame.size.height = self.myTextView.contentSize.height;
self.myTextView.frame = frame;
}
But it still show me textView that not fit whole rows of text (user can actually scroll it up and down, feature that i don't want to). How to change textView frame height for height, that actually fit whole text? And how to measure final height size of that textView?
Any advice would be appreciated, thanks!
You can try [self.myTextView sizeToFit]; and then see if it updates it for you.
- (CGFloat)heightForTextView:(UITextView*)textView containingString:(NSString*)string
{
float height = [self.model boundingRectWithSize:CGSizeMake(widthOfTextView, 20000000)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:[UIFont fontWithName:#"Helvetica Neue" size:15]}
context:nil].size.height + 16;
return height;
}

Adjust width of UILabel based on its contents

I had a look on SO before asking this question. All the questions are about adjusting the height of a UILabel and not its width. I tried alternative methods but it did not work such as [label sizeToFit];. Is it possible to adjust the width of a label based on its text? I create my label in a UITableViewCell in story board. I want to be able to adjust its width based on the text that it is assigned. I dont want to resize the font size.
I set the text of the label in CellForRowAtIndexPath.
Examples would be great please.
Thanks in advance :)
Update 1: I have a custom cell that I am making in Storyboard so not programmatically. I set the contents of each cell in CellForRowAtIndexPath, for example, myLabel.text = recipe.name. The name label is quite small, however I would like to extend its width based on the length of the text, not truncate the tail or shrink the size of the text.
Update2: I have a lot of other UIElements in the cell. So I have a label in the top left, top right, bottom left, bottom right, and a picture in the middle, there default is 120 because they have a background color. I set it small the there is not a huge amount of empty space in the label.
Get the size of the string:
//Replace FLT_MAX with the maximum height/width you want the label to be, if no maximum leave as FLT_MAX.
CGSize stringSize = [YOUR_STRING sizeWithFont:YOUR_FONT constrainedToSize:CGSizeMake(FLT_MAX, FLT_MAX) lineBreakMode:NSLineBreakByWordWrapping];
Then size your label:
[YOUR_LABEL setFrame:CGRectMake(0, 0, stringSize.width, stringSize.height)];
In iOS 7 sizeWithFont is deprecated, use boundingRectWithSize instead:
NSDictionary *stringAttributes = [NSDictionary dictionaryWithObject:YOUR_LABELS_FONT
forKey: NSFontAttributeName];
CGSize stringSize = [text boundingRectWithSize:CGSizeMake(FLT_MAX, FLT_MAX)
options:NSStringDrawingTruncatesLastVisibleLine |
NSStringDrawingUsesLineFragmentOrigin
attributes:stringAttributes context:nil].size;
CGSize maxSize = CGSizeMake(250, CGFLOAT_MAX); //250 is max desired width
CGSize textSize = [Label.text sizeWithFont:Label.font constrainedToSize:maxSize];
Label.frame = CGRectMake(0, 0, textSize.width, 15); // desired Bounds
Using above code you can get frame size for perticular text, & then resize label accordingly
You don't need to set explicit width for UILabel. UILabel provides intrinsic content size when used with autolayout. If you add constraints that provide the label's x,y position(Top Space constraint + Leading Space constraint), autolayout will be able to determine its width height based on the content.

heightForRowAtIndexPath with custom cell and label [duplicate]

This question already has answers here:
Calling heightForRowAtIndexPath from within cellForRowAtIndexPath?
(3 answers)
Closed 10 years ago.
If I'm making a custom UITableViewCell and I need it to have a variable height depending on the length of the input (for instance, for a Twitter reader or something), how can I make this work?
I've found lots of other examples here that can set it for a the standard, non-custom cell, but my cell's main text label is smaller, etc., so when I try to use any of those methods on my cell, they give a variety of weird results (text overlapping the bottom of the cell, etc.)
Is there a standardized way of designing the cell (for example, how tall should I make it in Interface Builder?), and let's say my label was half the width of that cell.. how would I go about calculating the height the cell would need to be to display the string loaded into that label? Here's a method that I found here which works fine on the normal cell, but screws up custom ones with weird heights, overlapping text, etc: (I have absolutely NO idea what the 300 / 200000 do here, if anyone could explain that I'd be grateful, too!)
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
CGSize textSize = {300.f, 200000.0f};
CGSize size = [[_quoteStringsFromPlist objectAtIndex: indexPath.row] sizeWithFont: [UIFont systemFontOfSize:12.0f] constrainedToSize: textSize lineBreakMode: NSLineBreakByWordWrapping];
size.height += 5.0f;
float result = MAX(size.height, 32.0f);
return result;
}
Something like this should work.
CGRect labelFrame = // enter default frame of the label here
UIFont *labelFont = // enter label font here
CGFloat labelBottomMargin = // enter the space between the bottom of the label and the bottom of the cell here
CGSize size = [labelString sizeWithFont:labelFont constrainedToSize:CGSizeMake(labelFrame.size.width, MAX_FLOAT)];
size.height += labeFrame.origin.y;
size.height += labelBottomMargin;
size.height = MAX(size.height, 32.0f);
return size.height;
First, head over to your xib file and see how large are the top/bottom margins of your text area, and how wide it is.
After that, you need to calculate the height needed for it with the width you have available, and then add that value to the top/bottom margins your text area already has.
The result should look correctly regardless of the size of each cell in IB or the text you are trying to put in them.
EDIT
Imagine your cell size is {700, 300} in your IB, and your text area is located on {{100, 100}, {300,100}}, your text area has a 100px margin top and 100px margin bot, and it's width is 300.
When you calculate the height you require for your text, you calculate it with an available 300 width. It will return a size, something like {300, 250}. That 250 is the height required by your text, but your cell has other stuff in it and you need to add those top and bot margins to that, so the result is 450.
Remember to set an autoresizing mask or autolayout so that your text area stretches vertically and the margins are fixed (UIViewAutoresizingFlexibleHeight)

Resources