How to know the displayed text in UILabel? - iphone

I have an UIView containing two UILabels, in order to display a string.
The first UILabel has a fixed size, and if the string is too long and can't hold in this UILabel, I want to display the maximum characters I can in the first UILabel, and display the rest of the string in the second UILabel.
But to make this, I must know the exact part of the string displayed in the first UILabel, which is not easy because of the randomness of the string and the linebreaks.
So, is there a way to get just the text displayed in the first UILabel, without the truncated part of the string?

if ([_infoMedia.description length] > 270) {
NSRange labelLimit = [_infoMedia.description rangeOfString:#" " options:NSCaseInsensitiveSearch range:NSMakeRange(270, (_infoMedia.description.length - 270))];
_descTop.text = [_infoMedia.description substringToIndex:labelLimit.location];
_descBottom.text = [_infoMedia.description substringFromIndex:(labelLimit.location+1)];
} else {
_descTop.text = _infoMedia.description;
_descBottom.text = #"";
}
Okay that's a late answer but maybe it could help someone. The code above is approximatively the solution I used in my app.
_descTop is my first label and _descBottom is the second label. 270 is a constant equivalent to a little less than the average maximum number of characters displayed in my first label, _descTop. I calculated it by hand, trying with many different strings, maybe there's a better way to do that but this worked not bad.
If the string I want to display (_infoMedia.description) is larger than 270 characters, I isolate the first 270 characters plus the end of the next word in the string (by searching the next space), in the case where the 270 characters limit would cut the string in the middle of a word. Then I put the first part of the string in my first label, and the second part in the second label.
If not, I only put the globality of the string in the first label.
I know that's a crappy solution, but it worked and I didn't found any better way to do that.

Following code might help you in getting what you want!!
//If you want the string displayed in any given rect, use the following code..
#implementation NSString (displayedString)
//font- font of the text to be displayed
//size - Size in which we are displaying the text
-(NSString *) displayedString:(CGSize)size font:(UIFont *)font
{
NSString *written = #"";
int i = 0;
int currentWidth = 0;
NSString *nextSetOfString = #"";
while (1)
{
NSRange range;
range.location = i;
range.length = 1;
NSString *nextChar = [self substringWithRange:range];
nextSetOfString = [nextSetOfString stringByAppendingString:nextChar];
CGSize requiredSize = [nextSetOfString sizeWithFont:font constrainedToSize:CGSizeMake(NSIntegerMax, NSIntegerMax)];
currentWidth = requiredSize.width;
if(size.width >= currentWidth && size.height >= requiredSize.height)
{
written = [written stringByAppendingString:nextChar];
}
else
{
break;
}
i++;
}
return written;
}
#end

Related

Know where a UILabel splits a string when its multi-line property is on

Have a problem, need to assign some text to a UIButton's title. Have set the buttons line break mode to NSLineBreakByCharWrapping so that the string is separated only by characters at end of each line. But i need to insert an hyphen at the end of the line to show continuity of the word.
Heres what i tried -
// Initialize the button
titleButton.titleLabel.lineBreakMode = NSLineBreakByCharWrapping;
titleButton.titleLabel.backgroundColor = [UIColor yellowColor];
[titleButton.titleLabel setFont:[UIFont fontWithName:#"Helvetica-Bold" size:15]];
// Make the string here
NSMutableString *titleString = [[NSMutableString alloc] initWithString:#"abcdefghijklmnopqrs tuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"];
// Insert hyphens
int titleLength = [titleString length];
int hyphenIndex = 19;
while (hyphenIndex<titleLength) {
UniChar charatIndex = [titleString characterAtIndex:hyphenIndex];
if ((charatIndex - ' ') != 0) { // Check if its not a break bw two words
[titleString insertString:#"-" atIndex:hyphenIndex]; // else insert an hyphen to indicate word continuity
}
hyphenIndex += 19; //Since exactly 20 char are shown in single line of the button's label.
}
//Set the hyphenated title for the button
[titleButton setTitle:titleString forState:UIControlStateNormal];
[titleString release];
This is the closest i could get.
Any help would be greatly appreciated.
Try NSAttributedString
It give a great possibilities for working with strings.
WWDC 2012-230
For example:
- (NSUInteger)lineBreakBeforeIndex:(NSUInteger)index withinRange:(NSRange)aRange
//Returns the appropriate line break when the character at the index won’t fit on the same line as the character at the beginning of the range.
your second word's length is more the length of line (width of button) thats why this happen.
pasting hyphens is not very good idea. You should split your string on parts with size that fits button's width by using than add hyphens if needed
[String sizeWithFont:font constrainedToSize:Size lineBreakMode:LineBreakMode]
The main idea is to get portion of initial string (add hyphen if word breaks), check if its width fits button's width. If width is smaller, try bigger part, else if fits -- process further part
See my answer here for how to use NSParagraphStyle and NSAttributedString to get a UILabel that breaks with hyphens: https://stackoverflow.com/a/19414663/196358

Based on number of lines in uitextview getting substring

Frrom UITextview i am able to get number of lines for given text, if its more than 4 lines i want to truncate the rest, so how to get the index to substring?
It will restrict to user to enter more than 4 lines in a UITextview
- (BOOL)textView:(UITextView *)aTextView shouldChangeTextInRange:(NSRange)aRange replacementText:(NSString*)aText
{
if (textView.contentSize.height/textView.font.lineHeight>4) {
return NO;
}
else
return YES;
}
NSMutableString *str = [[NSMutableString alloc] initWithString:textView.text];
static int numberOfLines = 0;
int nOC = 1;
while (nOC < [textView.text count] && numberOfLines < 4) {
if ([[str substringWithRange:NSMakeRange(nOC,1)] isEqualToString:#"\n"]; ) {
numberOfLines++;
}
nOC++;
}
NSString *finalString = [str substringWithRange:NSMakeRange(1,nOC)];
i hope this should work out for u. i calculated the number of characters till the 4th "\n" and used substringWithRange to extract the desired string. i didnt try this piece of code but this logic should work or at least assist u in your code. happy coding :)

Calculating enough text to fit within existing UILabel

I can't get some CoreText text wrapping code working for me; it's just too complicated. I'm going to try and go another route, which is to split my UILabel into two.
What I'm trying to achieve is to have my text appear to wrap around my fixed sized rectangular image. It'll always be the same dimensions.
So, when the UILabel next to the image fills up exactly, it'll create another UILabel below the image.
Now, how do I calculate the text in the first UILabel and have it fit nicely in the entire width of the UILabel, without being too short or cut off at the end?
Well, this ought to work to get the substring of the master string that will fit within the desired width:
//masterString is your long string that you're looking to break apart...
NSString *tempstring = masterString;
while (someLabel.bounds.size.width < [tempString sizeWithFont:someLabelLabel.font].width) {
NSMutableArray *tempArray = [NSMutableArray arrayWithArray:[tempString componentsSeparatedByString:#" "]];
//Remove the last object, which is the last word in the string...
[tempArray removeLastObject];
//Recreate the tempString with the last word removed by piecing the objects/words back together...
tempString = #"";
for (int i=0; i < tempArray.count - 1; i++) {
tempString = [tempString stringByAppendingFormat:#"%# ", [tempArray objectAtIndex:i]];
}
//You must append the last object in tempArray without the space, or you will get an infinite loop...
tempString = [tempString stringByAppendingFormat:#"%#", [tempArray objectAtIndex:tempArray.count - 1]];
}
//Now do whatever you want with the tempString, which will fit in the width desired...
Of course, this is assuming you want the separation to occur using word wrapping. If you don't mind words themselves being cut apart (i.e. character wrap) in order to fully take up the desired width, do this instead:
NSString *tempstring = masterString;
while (someLabel.bounds.size.width < [tempString sizeWithFont:someLabelLabel.font].width) {
tempString = [tempString substringToIndex:tempString.length - 1];
}
//Now do whatever you want with the tempString, which will fit in the width desired...
In order to get the remaining piece of the string left over, do this:
NSString *restOfString = [masterString substringFromIndex:tempString.length];
Hope this helps. I have to admit that I haven't properly tested this code yet, though I've done something similar in the past...
Try below link its will help you.
If you want to create a "link" on some custom text in your label, instead of using a WebView as #Fabian Kreiser suggested, you sould use my OHAttributedLabel class (you can find it this link)
See the sample code provided on my github repository: you can use my addCustomLink:inRange: method to add a link (with a customized URL) to a range of text (range that you could determine by iterating over every occurrences of the word "iPhone" in your text very easily). Then in the delegate method on OHAttributedLabel, you can catch when the link is tapped and act accordingly to do whatever you need.

Ellipsis at the end of UITextView

If I have multi-line non-scrollable UITextView whose text is longer than can fit in the visible area, then the text just cuts off like so:
Congress shall make no law respecting
an establishment of religion, or
How would I get the text to show with an ellipsis where the text cut-off is, like so
Congress shall make no law respecting
an establishment of religion, or …
Other controls like labels and buttons have this ability.
Why not use a UILabel setting numberOfLines to something appropriate and getting that functionality for free?
The UITextView is designed to scroll when the string is larger than what the view can show. Make sure that you have set the anchoring and autoresize attributes correctly in code or your xib.
Here is an example from a blog post about how to implement your own ellipsis.
#interface NSString (TruncateToWidth)
- (NSString*)stringByTruncatingToWidth:(CGFloat)width withFont:(UIFont *)font;
#end
#import "NSString+TruncateToWidth.h"
#define ellipsis #"…"
#implementation NSString (TruncateToWidth)
- (NSString*)stringByTruncatingToWidth:(CGFloat)width withFont:(UIFont *)font
{
// Create copy that will be the returned result
NSMutableString *truncatedString = [[self mutableCopy] autorelease];
// Make sure string is longer than requested width
if ([self sizeWithFont:font].width > width)
{
// Accommodate for ellipsis we'll tack on the end
width -= [ellipsis sizeWithFont:font].width;
// Get range for last character in string
NSRange range = {truncatedString.length - 1, 1};
// Loop, deleting characters until string fits within width
while ([truncatedString sizeWithFont:font].width > width)
{
// Delete character at end
[truncatedString deleteCharactersInRange:range];
// Move back another character
range.location--;
}
// Append ellipsis
[truncatedString replaceCharactersInRange:range withString:ellipsis];
}
return truncatedString;
}
#end
Someone just showed me that it's actually really easy to do this with UITextView on iOS 7 and up:
UITextView *textView = [UITextView new];
textView.textContainer.lineBreakMode = NSLineBreakByTruncatingTail;

UITextView how to cut off text

I have a UITextView that is displaying a facebook status loaded from Facebook Connect. I'm trying to make it so that the UITextView is just creating a preview of the text. I want it to look like it does when there is too much text for a UILabel. It would be something like "There is too much text..." with the dots but UITextViews don't do that. Does anybody know how to get it to work?
Write a separate method that counts how many letters there are in the string and if there are more than some preset value then cut it and append three dots to the end.
Also, consider using UILabels instead of UITextViews if you don't need to edit information inside since UITextViews take longer to allocate and init and are generally slower than UILabels.
+(NSString *)getTruncatedTextForString:(NSString *)inputString withFont:(UIFont *)font withLength:(int)textViewlength
{
CGSize dotSize=[#"..." sizeWithFont:font];
float dotWidth=dotSize.width;
NSString *outputString=#"";
int reqLength=textViewlength-dotWidth;
for(int i=0;i<inputString.length;i++)
{
NSString *tempStr=[outputString stringByAppendingString:[inputString substringWithRange:NSMakeRange(i,1)]];
if([tempStr sizeWithFont:font].width>reqLength)
{
break;
}
else
{
outputString=tempStr;
}
}
NSString *tempStr=[outputString stringByAppendingString:#"..."];
outputString=tempStr;
return outputString;
}
Try the below code. It will display two dots to the textview with text more than its frame height.
if(textview.contentSize.height > textview.frame.size.height)
{
while (textview.contentSize.height > textview.frame.size.height)
{
textview.text = [textview.text substringWithRange:NSMakeRange(0, textview.text.length-1)];
}
textview.text = [textview.text substringWithRange:NSMakeRange(0, textview.text.length-2)];
textview.text= [NSString stringWithFormat:#"%#..",textview.text];
}
It works, only when we set the correct height to the UITextview with respect to the font and fontsize of that textview.
For ex, if the font is bold system font of size 16 means, the textview height should be of minimum 30.