Dynamic expand UITextView - ios

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.

Related

How to increase height of text view when i type return key in key board?

How to increase height of text view when i type return key in key board?
please give me solution .
there are many views on top.
need i to set frame of all view or just decreasing height of table view i will get solution?
Well, every time you hit 'Enter' on keyboard, you have to resize (height) the UITextView, and also resize (height) the UITableView accordingly as well.
Try this code it will set the height of the TextView according to it's content.
[txtAddress setFrame:CGRectMake(20, 90, 280, [self contentSizeRectForTextView:txtAddress])];
Method for TextView height:
- (CGFloat)contentSizeRectForTextView:(UITextView *)txtView
{
[txtView.layoutManager ensureLayoutForTextContainer:txtView.textContainer];
CGRect textBounds = [txtView.layoutManager usedRectForTextContainer:txtView.textContainer];
CGFloat height = (CGFloat)ceil(textBounds.size.height + txtView.textContainerInset.top + txtView.textContainerInset.bottom);
return height;
}
When setting new frame size, your view frame origin should still be the same but the frame height.
[textView setFrame: CGRectMake(textView.frame.origin.x,textView.frame.origin.y,textVie.frame.size.width,<new height>)];

UITextView text becomes invisible after height reaches 8192.0

I have a non-scrollable UITextView embedded in a UIScrollView and add text to the UITextView dynamically. The UIScrollView adjust it's contentSize accordingly based on the TextView's frame. However, once the UITextView exceeds a height of 8192, the text will become invisible (but still there, because you can use the magnifying glass to highlight text and even see parts of the text through the magnifying glass).
CGRect textviewFrame = self.TextView.frame;
textviewFrame.size.height = [self textViewHeightForAttributedText:self.TextView.attributedText andWidth:320.0];
self.TextView.frame = textviewFrame;
self.ScrollView.contentSize = self.TextView.frame.size;
Helper function to size UITextView accordingly:
- (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;
}
Didn't realize it was the same exact problem that was unsolved here until I tested it out explicitly by forcing the max size to 8193 and the problem occurred (while a max size of 8192 still had the text showing correctly). Anyone run into this problem before and know of a work around? Thanks
I was recently hit by this problem and have worked out an effective way around it. Although it seems like an iOS bug IMHO it's really not... there are practical limits to CALayer sizes, plus drawing an 8K high piece of text takes a long time. Much better to do as Apple intended and to only render the bit of text that's visible... that's why UITextView extends UIScrollView after all.
The problem is that UITextView isn't terribly easy to integrate with other bits of UI. In my case I am working on a news app where a single UITextView is used to render the article, plus there's some separate UI (titles and buttons etc) above and below it, all hosted in a single scrollable container.
The solution I've found is to split the UITextView into two views... a dedicated UITextView container whose frame is the full text size (i.e. the same size your UITextView's contentSize) and which is the superview of your UITextView. Your child UITextView's frame should be set to the bounds of the outer scrollable container.
Then all you have to do is use key-value observation to monitor the contentOffset property of your outer scrollable container view (in my case this is a UICollectionView). When its contentOffset changes you update (1) the contentOffset of your UITextView, and (2) the transform property of the UITextView's layer. By updating that transform property the UITextView is fixed to fill the currently-visible part of it's superview. But because you're also updating the UITextView's contentOffset, this trickery is totally invisible to the user... it looks and behaves as if the UITextView is simply very large.
Here's a fully functional solution, for anyone who'd like it!
** Assuming your content size will not exceed the limits of two text views **
This solution works by adding two UITextViews to your view, and splitting your text between them. It looks complicated, but it's actually very simple! I've just written a very verbose description :)
Step 1 - Add two UITextViews to your view:
I added mine in my storyboard. Place them so that one is directly above the other, with no space between them. Don't worry about setting the height (we will set that later).
Set constraints on the views so that they are tied to each other from the top and bottom, and the surrounding edges of the container from all other sides, including your desired padding. i.e. tie the first text view to the container from the top, left, and right, and to the second text view from the bottom. Tie the second text view to the container from the bottom, left, and right, and to the first text view from the top. This will ensure that they stretch appropriately when the content is set.
Don't set any constraints on the height of the views, or if you must (to avoid warnings from the constraints inspector), set the height of one of the views to be >= 20, or some similarly small number.
Disable scrolling, bouncing, and scrolling indicators for both your text views. This solution relies on the views being a fixed, non-scrollable height, so if you'd like your content to scroll, you should use a UIScrollView or UITableViewCell as a container.
Create outlets for your two new text views in your view controller file, naming them something like textView1 and textView2.
Step 2 - Set textContainerInsets to zero:
Set the textContainerInset property on both text views to zero, either using User Defined Runtime Attributes:
or code:
self.textView1.textContainerInset = UIEdgeInsetsZero;
self.textView2.textContainerInset = UIEdgeInsetsZero;
This will ensure that the no visible space will appear between the two views when the content is set, and should not affect the other spacing around your views.
Step 3 - Split your content, set it, and update the view heights:
Simply copy the following code into your view controller file (viewDidLoad), and set the contentString variable to your content.
/* Content is split across two UITextViews to avoid max drawing height */
NSString *contentString = #"Some very long piece of text...";
// Set text
NSArray *components = [contentString componentsSeparatedByString:#"\n"];
NSInteger halfLength = [components count] / 2;
NSArray *firstHalf = [components subarrayWithRange:NSMakeRange(0, halfLength)];
NSArray *secondHalf = [components subarrayWithRange:NSMakeRange(halfLength, [components count] - halfLength)];
NSString *contentString1 = [firstHalf componentsJoinedByString:#"\n"];
NSString *contentString2 = [secondHalf componentsJoinedByString:#"\n"];
self.textView1.text = contentString1;
self.textView2.text = contentString2;
// Set text view heights
CGFloat fixedWidth1 = self.textView1.frame.size.width;
CGFloat fixedWidth2 = self.textView2.frame.size.width;
CGSize newSize1 = [self.textView1 sizeThatFits:CGSizeMake(fixedWidth1, CGFLOAT_MAX)];
CGSize newSize2 = [self.textView2 sizeThatFits:CGSizeMake(fixedWidth2, CGFLOAT_MAX)];
CGRect newFrame1 = self.textView1.frame;
CGRect newFrame2 = self.textView2.frame;
newFrame1.size = CGSizeMake(fmaxf(newSize1.width, fixedWidth1), MIN(newSize1.height, 8192));
newFrame2.size = CGSizeMake(fmaxf(newSize2.width, fixedWidth2), MIN(newSize2.height, 8192));
self.textView1.frame = newFrame1;
self.textView2.frame = newFrame2;
This code splits the contentString roughly in the middle, looking for the nearest newline. If you'd like to split your content on a different character, simply change all occurrences of \n above to whatever you'd like to split on.
Step 4 - Set your container view height:
Set your container view (scrollView, tableViewCell, whatever else) to the height of your two text views, plus whatever additional space you've set above and below them.
CGRect viewFrame = self.myView.frame;
viewFrame.size.height = MIN(self.textView1.frame.size.height, 8192) + MIN(self.textView2.frame.size.height, 8192) + kTextViewContainerPadding;
[self.myView setFrame:viewFrame];
(In my code, kTextViewContainerPadding is a macro I've set to the sum of the space above and below my two text views, within their container).
That's it! Good luck.
Try enabling the scroll for the scrollView.
Keep the height of the textView > height of the content, so that in reality there will be no scroll, but scrollEnabled should be = YES
It solved the problem for me.
Hello I think am not late to answer. I got the same problem like you. This is my solution:
textView.scrollEnabled = YES;
contentTextView.attributedText = finalAttrString;
// contentTextView.text = [attrString string];
contentTextView.font = kFont(contentTextFS + [valueOfStepper intValue]);
[contentTextView sizeToFit];
contentTextView.height += 1;//This is the key code
//contentTextView.height = 8192.0f
Them I solved the trouble and I can change size dynamic.Successfull on iOS 8

How to make UITextView so high that it exactly fits the text content on iOS7?

I have a UITextView that's embedded into a UIScrollView. I would like the text view to not scroll and be exactly as high as required to show all of the text.
So the width is fixed and I set the content insets to indent the text a bit.
How do I get the correct height? I tried to set the frame's height to the content height but still it scrolls.
This should do the trick:
-(void)resizeTextView
{
CGRect frame = _textView.frame;
frame.size.height = [_textView sizeThatFits:CGSizeMake(frame.size.width, INFINITY)].height;
_textView.frame = frame;
}

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

Autoexpand UITextView height to contain the complete text loaded dynamically

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:

Resources