Autoexpand UITextView height to contain the complete text loaded dynamically - ios

I have a simple textView who's data gets populated dynamically. I want to resize the height of the textview once the data is populated so that i dont see a vertical scroll nor the text gets clipped.
Could it be done simply by choosing one of those textView modes or do i need to do it programaticaaly?

You can do this by adding these few lines of code to your application's:-
CGRect frame = textView.frame;
frame.size.height = textView.contentSize.height;
textView.frame = frame;
Implement this code in th delegate method of textview
- (void)textViewDidChange:(UITextView *)textView
{
// you might have to compare the frames if it needs changing as user might not have added an extra line
}

You have to do it programmatically. Use the NSString UIKit Additions to calculate the height of your UITextView:
sizeWithFont:
sizeWithFont:constrainedToSize:
sizeWithFont:constrainedToSize:lineBreakMode:
sizeWithFont:forWidth:lineBreakMode:
sizeWithFont:minFontSize:actualFontSize:forWidth:lineBreakMode:

Related

Change ScrollView height based on content of the View

I parse some Json Data and I show it using various UITextView, for now I used a ScrollView created via Storyboard that has a height of 1000px but sometimes I can't show the whole data since it's too long to fit the ScrollView, how can I update it programmatically in order to have a height based on the content the view has to show?
You may calculate the height of text:
CGRect textRect = [#"your text" boundingRectWithSize:CGSizeMake(yourScrollView.width, CGFLOAT_MAX)
options:(NSStringDrawingUsesLineFragmentOrigin)
attributes:#{NSFontAttributeName:[UIFont fontWithName:#"HelveticaNeue" size:18]}
context:nil];
And then update scrollView contentSize
[yourScrollView setContentSize:CGSizeMake(yourScrollView.frame.size.width,textRect.size.height)];
Go to your storyboard and remove all height constraint of your UITextViews. In order to avoid warnings in the storyboard, select Intrinsic Size -> Place Holder for each UITextView in your ScrollView. The option is located in the Size Inspector (right pane). This will tell XCode know that you don't want to specify a height, you rather want them to be based on its intrinsicContentSize.
Finally, create a new class 'FitContentTextView' that inherits from UITextView. In the storyboard make all your UITextView's that you want to have enough size to fit content of type FitContentTextView
- (void)setText:(NSString *)text {
[self setScrollEnabled:YES];
[super setText:text];
[self invalidateIntrinsicContentSize];
}
- (CGSize)intrinsicContentSize {
CGSize size = [self contentSize];
return size;
}
The setScrollEnabled thing in setText is important. The method contentSize only returns enough size to fit all text if srolling is enabled. Otherwise, will return the the TextView's bounds.
Also, calling invalidateIntrinsicContentSize every time we set the text makes sure autolayout will call the method intrinsicContentSize before drawing the TextView, and add this methods to it.
Lastly, remember to pin all ScrollView's subviews vertically to its superview from top to bottom. This is the only way AutoLayout can update the contentSize of the SrollView to fit all subviews.

Autoresizing UITextView IOS7

I did a lot of research but none helped with my current situation. What I want to do is have an auto resizing UITextView that grows as the user types. It starts off with a default height and auto grows as the text increases. I added to UITextView to my UIView using the interface builder. now I just need help with making it auto grow. The answers I found said in IOS7 you use [myTextView sizeToFit] which makes it auto-resize but looks like this only works for UITextViews that are added programmatically.
I made a subclass of UITextView just for that:
https://github.com/MatejBalantic/MBAutoGrowingTextView
It is an auto-layout based light-weight UITextView subclass which automatically grows and shrinks based on the size of user input and can be constrained by maximal and minimal height - all without a single line of code.
Made primarily for use in Interface builder and only works with Auto layout.
You will need to set a delegate for myTextView and have it respond to changes in its text.
In your view controller's interface declare that it conforms to the UITextViewDelegate protocol, e.g.:
#interface MyViewController : UIViewController <UITextViewDelegate>
In your view controller's -viewDidLoad add this:
self.myTextView.delegate = self;
Then implement the -textViewDidChange: delegate method:
- (void)textViewDidChange:(UITextView *)textView
{
if (textView != self.myTextView)
return;
CGFloat const horizontalPadding = 16.0f; // experiment with these padding values
CGFloat const verticalPadding = 16.0f; // until the textview resizes nicely
CGSize maxSize = CGSizeMake(textView.bounds.size.width - horizontalPadding, CGFLOAT_MAX);
CGSize textSize;
if ([textView.text respondsToSelector:#selector(sizeWithAttributes:)]) {
// iOS7 and above
NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
[NSValue valueWithCGSize:maxSize], NSViewSizeDocumentAttribute,
textView.font, NSFontAttributeName, nil];
textSize = [textView.text sizeWithAttributes:attributes];
} else {
// iOS6 and below
textSize = [textView.text sizeWithFont:textView.font
constrainedToSize:maxSize
lineBreakMode:NSLineBreakByWordWrapping];
}
CGRect newFrame = textView.frame;
newFrame.size.height = textSize.height + verticalPadding;
textView.frame = newFrame;
}
I would suggest you try HPGrowingTextView before using a custom solution.
In case you do not like it, you would go about it like this:
Create a UITextView with an initial frame and add it to a UIView.
Override the textViewDidChange: method and get a CGSize of the content using yourTextView.contentSize property.
Use the height property of this CGSize to set the height of your UITextView using CGRectMake.
The contentSize gives you the exact size of the content in your textView, without using sizeWithFont:(deprecated) or sizeWithAttributes:.
But here's the catch: If your textView is contained inside another UIView, you might have to set it's autoresizingMasks to UIViewAutoresizingFlexibleTopMargin, UIViewAutoresizingFlexibleBottomMargin, UIViewAutoresizingFlexibleHeight as per your need, for the succesful resizing of superviews of the textView.
Try going through the code of HPGrowingTextView, and you will understand how this behaviour is implemented.

How to find out when UILabel wordwraps

I have created a couple of different UITableViewCells for my tableViewController, this is because I have different bits of data I want to display depending what comes back. Because of this each UITableViewCell is of a different height.
This is all fine, However one of my UILabels has to display a large NSString, so large that I have had to word wrap it onto a second line, The only issue here is that it messes up my UITableViewCell formatting.
My question is, is it possible to flag or capture some type of action when a UILabel receiving a NSString has to use wordrap because the size of the NSString is too long?
Or is there a way to calculate the physical length (not how many chars are in the string) of the NSString so I can decide hey I need to reformat my UITableViewCell..
Any help would be greatly appreciated.
The usual way is to use sizeWithFont:constrainedToSize:lineBreakMode: to get the size of a string. You use it like this:
CGSize stringSize = [theString sizeWithFont:[UIFont fontWithName:#"Helvetica Neue" size:12] constrainedToSize:CGSizeMake(320, 3000) lineBreakMode:NSLineBreakByWordWrapping ];
This is set for the full width of a table cell, but you would want to use the width of your label instead.
i dont know if i understand well but you have the height of your tableviewcell right? and you have a NSString maybe in a UITextView and this height of content of textview is higher then tableviewcell. Well, you should first calculate the content of UITextview, add into a list and when heightforRowAtindexPath was called, you should calculate new height (content textview) plus something... And to solve the max length you should count a limit for chars or limit for lines..
Some usefull code:
//resize height with content of UITextView
CGRect frame = _textView.frame;
frame.size.height = _textView.contentSize.height;
_textView.frame = frame;
//delegate textview to calculate limit for text.
- (void)textViewDidChange:(UITextView *)textView{
NSInteger restrictedLength=140;
NSString *temp=textView.text;
if([[textView text] length] > restrictedLength){
textView.text=[temp substringToIndex:[temp length]-1];
}
}
remember, you need to calculate the limit/size content from UITextview before heightforRowAtIndexPath called. When it called you already need to know your max height for cell.

ios autolayout similar

I'm pretty new to ios. And while writing my first app i'v encountered that autolayout is only for ios 6.0. And i'd wish to make my app for at least 5.0 ios.
Maybe anyone would know how to make this without autolayout.
I have label which has dynamic text, 1row or 2 rows or 3 rows depends on user settings. And below it i have uitextfield. With autolayout i have no headache as it does all the work, the textfield sits nicely below in 1 2 or 3 rows of text above (resizes, moves automatically).
So how should i do this without autolayout?
Without autolayout you have to handle this in code. The recommended way of doing this would be to subclass your container view (the view that contains your label and text filed) and override the layoutSubviews method. In there you set the frames of the view's subviews manually, based on your desired criteria (e.g., the label text metrics).
EDIT: here's a specific example of something that could be in the containverView layoutSubviews method (typed from the top of my head):
// Those could be IBOutlets, or obtained by inspecting self.subviews
UILabel *label = self.label;
UITextField *textField = self.textField;
// Determine the labelSize, we could limit the maxSize (especially the height) manually here
CGSize maxSize = self.bounds.size;
CGSize labelSize = [label.text sizeWithFont:label.font constrainedToSize:maxSize lineBreakMode:label.lineBreakMode];
// Set the computed label size
CGRect labelFrame = label.frame;
labelFrame.size = labelSize;
label.frame = labelFrame;
// Now move the textField just below the label (we could also add a vertical margin here if we want)
CGRect textFieldFrame = textField.frame;
textFieldFrame.origin.y = labelFrame.origin.y + labelFrame.size.height;
textField.frame = textFieldFrame;
This just makes sure the text field is always below the label. Depending on the constraints you had in place, you might need to add more code to make sure the UI lays out correctly.
You also need to make sure that [containverView setNeedsLayout] gets called when the label text changes.
if you are using nib or storybord you can just remove the mark in the file inspector

Dynamic expand UITextView

I have UITextView and I want to expand it dynamically. If the text is should scroll I want to expand the view to fit the amount of the text. How can I do that. Thanks
When you end the editing of your text write this.
- (void) textViewDidEndEditing:(UITextView *)textView
{
CGRect frame = myTextView.frame;
frame.size.height = myTextView.contentSize.height;
myTextView.frame = frame;
}
You will have to find the heightof the text you need to contain inside the UITextView (of a particular fixed width) and then set its frame height to that value so that it is not scrollable. You can go through this example to see how exactly to do that.

Resources