How can I know that the text is out of fit (that the text is need to be scrolled)?
Does it have any methods or something to do this?
Thanks.
Use the NSString UIKit additions. They allow to calculate the height of a string given the size and font. So you can calculate the height in this way:
CGFloat textViewWidth = CGRectGetWidth(textView.bounds);
CGSize inset = CGSizeMake(5.0,5.0);
CGSize stringSize = [myString sizeWithFont:textView.font constrainedToSize:CGSizeMake(textViewWidth-2*inset.width,1024) lineBreakMode:UILineBreakModeWordWrap];
BOOL textOutOfFit = stringSize.height+2*inset.height>CGRectGetHeight(textView.bounds);
Note that this code requires some fine tuning. Infact text inside text views has some internal margin (that I took into account using the inset structure), so the required text view height will be higher than the calculated string height.
What this code does is to ask NSString to calculate its size when horizontally constrained in the textview boundaries (while 1024 in the height is the maximum UIView height possible).
Then what I do is to check if the returned string height is inside or not the text view boundaries.
Related
I have dynamic no of textviews and their size can also be dynamic, after each text view there are also dynamic no of labels, and each item is place on scroll view, so that scroll view also has dynamic size, So Someone guide me how to accomplish this task?
forgive me if this is repetitive question plz!
For setting dynamic height of UILabel or UITextView, you can implement following method
This example is for UILabel, Remember, you need to set noOfLines property before setting dynamic height, you can set noOfLines to max number.
NSString *text = #"Your text here";
CGSize size = [text sizeWithFont:lblName.font constrainedToSize:CGSizeMake(lblName.frame.size.width, 10000)];
scrollview.contentSize = CGSizeMake(scrollView.frame.size.width, size.height);
Hope this helps
What you need,
1 calculate textsize which you are going to to show on differnt controls.
for this use this line
[titleString sizeWithFont:[UIFont systemFontOfSize:14] constrainedToSize:CGSizeMake(285,9999) lineBreakMode:UILineBreakModeWordWrap];
2 Also use labels instead of textView at each place if you only need to show text.
because textViews justify the text means your same line can be fit in one line but also in two lines
3 set the scrollView contentSize as above answers says.by adding all textSizes with consider some spaces between various controls.
you can set the size of scrollview using setContentSize: and query size [scrollView contentSize]
I am trying to work out the size of a size of a textView up to the cursor by trimming all the text after the cursor, and then using NSString's sizeWithFont method, like so:
NSString *string = [myTextView.text substringToIndex:myTextView.selectedRange.location];
CGSize size = [string sizeWithFont:myTextView.font constrainedToSize:myTextView.frame.size lineBreakMode:UILineBreakModeWordWrap];
Unfortunately, this never returns quite the right size, probably because the text has margins, so its actual width is less than UITextView's width (thanks to the answerers of this question for working that out).
So I need to work out the size of the margins, and subtract that from the UITextView's size to get the actual size of the text area. Does anyone know how to do that?
Unfortunately it looks like the answer is that there is no margin in UITextView - you just have to simulate one by putting a view behind it, and making the UITextView narrower. If you need the background to scroll with the text, you can listen for scrollViewDidScroll:.
I'd suggest
CGSize tSize = myTextView.frame.size;
tSize.width -= 2 * myTextView.contentInset.left;
tSize.height -= 2 * myTextView.contentInset.top;
CGSize size = [string sizeWithFont:myTextView.font constrainedToSize:tSize lineBreakMode:UILineBreakModeWordWrap];
Is there an equivalent to NSString's sizeWithFont: method that can be used for calculating the height of text in a UITectView for a given width? All of the methods from NSString only operate on a single line from what I can tell.
From Apple's reference for these NSString methods, you could use -sizeWithFont:constrainedToSize: or -sizeWithFont:constrainedToSize:lineBreakMode: for "Computing Metrics for Multiple Lines of Text".
CGSize size = [theString sizeWithFont:font
constrainedToSize:CGSizeMake(width, 100000)];
return size.height;
For UITextView, all you have to do is call -sizeToFit on the view, and it will automatically resize its height until it can fit all the text available. All you need to do is set the width of the text view, set the text, then call -sizeToFit. The text view will resize its height just enough to fit all the text.
UPDATE:
Apparently text views only shrink when there's excess height, but they don't grow if there's insufficient height to display all the text. In addition, once you call -sizeToFit, the text view's y coordinate is reset back to 0.0f. So here's what you do:
CGFloat textViewWidth = 300.0f;
CGFloat textViewPadding = 10.0f;
UITextView * textView = [[[UITextView alloc] init] autorelease];
textView.text = ...; // Really long string
textView.frame = CGRectMake(0.0f, 0.0f, textViewWidth, CGFLOAT_MAX);
[textView sizeToFit]; // Shrinks the height to fit all the text
textView.frame = CGRectMake(textViewPadding, textViewPadding,
textViewWidth, textView.frame.size.height);
[self.view addSubview:textView];
First, you set the frame just so you can set the width like you want it. You use CGFLOAT_MAX to pretty much indicate infinite height. Next, calling -sizeToFit shrinks the height until it just fits all the text. However, it also resets the y coordinate, so we go ahead and set the frame again to configure the x and y coordinates—in this example, 10.0f for both x and y—, leaving the width alone and keeping the height set to whatever -sizeToFit calculated.
actually, you could use the property contentSize.
Is there a way to get the correct size of an NSString using:
- (CGSize)sizeWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode
that doesnt get thrown off by 2 or 3 hundred character strings. At the moment if I try to use this method on these long strings it incorrectly calculates them and I end up with lots of whitespace at the bottom of the UITextView.
I've tried using UILineBreakModeWordWrap and UILineBreakModeCharacterWrap.
the resizing is being done in
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
CGFloat result = 44.0f;
NSString* text = nil;
CGFloat width = 0;
CGFloat tableViewWidth;
CGRect bounds = [UIScreen mainScreen].bounds;
tableViewWidth = bounds.size.width;
width = tableViewWidth - 150;
text = stringWithLongWords;
if (text) {
CGSize textSize = { width, 20000.0f };
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:10.0f] constrainedToSize:textSize lineBreakMode:UILineBreakModeWordWrap];
size.height += 50.0f;
result = MAX(size.height, 44.0f+30.0f);
}
return result;
}
UITextView is not exactly like a UILabel wrapped in a UIScrollView. It has line spacing different from the font size and margins that sizeWithFont:constrainedToSize:linkBreakMode: doesn't account for.
Knowing your font size you might be able to calculate the # of lines and take line spacing into account. You can guess at the margins and try to trick sizeWithFont: to give a more useful answer.
The popular solutions seem to be:
just use a UILabel if you don't need any UITextView functionality
if you need hyperlinks, overlay UIButtons that look like hyperlinks over a UILabel
use an off-screen UITextView and its sizeToFit method to get a real answer
I had no luck w/ the 3rd option but it sounds like it should work, so perhaps I did something wrong.
I'm going to try using a UILabel and overlaying buttons for hyperlinks. We'll see how that turns out.
If that fails, there is always the option taken by Loren Brichter (of Tweetie fame): draw everything into a UIView yourself using CoreGraphics.
Good luck!
Check out this post How do I size a UITextView to its content?
It looks like textView.contentSize.height should work (with the caveat that the the correct contentSize is only available after the UITextView has been added to the view with addSubview)
You said that you have a UITableView with differing heights. Have you set the reuse identifier to the same thing for all of the cells? It could be that older cells with their height already set are being reused. If this is the problem, you should resize the cell again when it's being reused.
The best solution I have found so far is to have a separate hidden UITextView with the same font settings, and set its text. After that its contetSize should be accurate.
The width you are using is the width for your UITextView... but you aren't concerned with that width, you are concerned with the width of the actual text area nested inside the text view.
UITextViews, by default, have padding around their borders to produce a space in-between the typed text and the edge of the UITextView a few pixels wide (and long for the top)... To get the correct size you shouldn't use
textView.frame.size.width
but rather,
textView.frame.size.width-(textView.contentInset.left+textView.contentInset.right+textView.textContainerInset.left+textView.textContainerInset.right+textView.textContainer.lineFragmentPadding/*left*/+textView.textContainer.lineFragmentPadding/*right*/)
^Which takes the width of the UITextView and subtracts out all the padding so you are left with the width of just the type-able text area.
Same goes for height except for lineFragmentPadding doesn't have a bottom so you only subtract it out once instead of twice.
The final code is something like this:
CGSize textViewContentSize = CGSizeMake(theTextView.frame.size.width-(theTextView.contentInset.left+theTextView.contentInset.right+theTextView.textContainerInset.left+theTextView.textContainerInset.right+theTextView.textContainer.lineFragmentPadding/*left*/+theTextView.textContainer.lineFragmentPadding/*right*/), theTextView.frame.size.height-(theTextView.contentInset.top+theTextView.contentInset.bottom+theTextView.textContainerInset.top+theTextView.textContainerInset.bottom+theTextView.textContainer.lineFragmentPadding/*top*//*+theTextView.textContainer.lineFragmentPadding*//*there is no bottom padding*/));
CGSize calculatedSize = [theTextView.text sizeWithFont:theTextView.font
constrainedToSize:textViewContentSize
lineBreakMode:NSLineBreakByWordWrapping];
CGSize adjustedSize = CGSizeMake(ceilf(calculatedSize.width), ceilf(calculatedSize.height));
Inspired by #MrNickBarker's answer, here's my solution:
CGFloat width = 280.0f;
UITextView *t = [[UITextView alloc] init];
[t setFont:[UIFont systemFontOfSize:17]];
[label setText:#"some short or long text, works both"];
CGRect frame = CGRectMake(0, 0, width, 0);
[t setFrame:frame];
// Here's the trick: after applying the 0-frame, the content size is calculated and can be used in a second invocation
frame = CGRectMake(0, 0, width, t.contentSize.height);
[t setFrame:frame];
The only issue remaining for me is that this doesn't work with modified insets.
Still can't believe such twists are required, but since -[NSString sizeWithFont:forWidth:lineBreakMode:] does not respect insets, paddings, margins, line spacings and the like, it seems this is the only working solution at the moment (i.e. iOS 6).
Imagine a UILabel, which is 200 pixels wide and 50 pixels high. The label has text inside, and the label makes the text smaller so that it fits into the label. But now, how would you get the size of that UIFont how it is visible in the label? Lets imagine the font size was given with huge 100, and the label squeezes it down to 15. And then, you want to make some other labels with little text, which has same font size. Is there a way to obtain the UIFont's font size after getting squeezed by the label?
If you pass the size of the UILabel and the breakMode, etc. to:
CGSize size = [label.text sizeWithFont:label.font minFontSize:10 actualFontSize:&actualFontSize forWidth:200 lineBreakMode:UILineBreakModeTailTruncation];
actualFontSize should be what you are looking for.
UPDATE:
The above has been deprecated. The method to use now is:
- (CGRect)textRectForBounds:(CGRect)bounds
limitedToNumberOfLines:(NSInteger)numberOfLines
Here's an example
CGSize size = [label textRectForBounds:label.bounds
limitedToNumberOfLines:1].size;