Calculate part of the text truncating the UILabel - ios

I have a UILabel that contains some text that is more than the size of UILabel. I don't want to change UILabel size i only want one line in it. So my question is how can i skip(remove) the text from end that is causing the UILabel to truncate tail?

I'm afraid there is no a direct method to calculate. But as you can get the size or bounds of a text using boundingRectWithSize:options:attributes: you can iterate using a dichotomic search algorithm and find the string position to cut from.

Use this line to set up the line break mode of your UILabel:
self.lineBreakMode = UILineBreakModeWordWrap

Try this,
I think you are asking for character wrapping trick.
First try in XIB
yourLabel.numberOfLines = 1;
yourLabel.lineBreakMode = NSLineBreakByCharWrapping;
//or
yourLabel.lineBreakMode = NSLineBreakByClipping;

I was doing a similar thing on UITableView Cell recently. This approach is flexible, as you can set any number of lines depending on height you have available. Everything else will be truncated. Check it out:
CGSize maxNameLabelSize = CGSizeMake(350,60); //setting height, you can limit it to one line depending on the font
UILabel *eventName = (UILabel*) ([activityCell.contentView viewWithTag:EVENT_TITLE]);
//Set value here
eventName.text = event.name;
CGSize expectedNameLabelSize = [eventName.text sizeWithFont:eventName.font constrainedToSize:maxNameLabelSize lineBreakMode:eventName.lineBreakMode];
CGRect newNameFrame = eventName.frame;
newNameFrame.size.height = expectedNameLabelSize.height;
eventName.frame = newNameFrame;
Does it makes sense?

Related

Adding multiple lines to a UILabel that is updated by a UITextField

So i'm making an application where the user converts the data from a UITextField into a UILabel. However, when updating a large amount of text instead of overflowing into another line, it simply displays '...' when there are too many words. I've tried changing the number of lines in the UILabel, even changing it to '0' which should mean the text displayed should fit the words in the UITextField, but this isn't the case. The following code I have for the UITextField to the UILabel is:
- (IBAction)add:(id)sender {
NSString *input = text1.text;
label1.text = input;
NSString *Input = text2.text;
label2.text = Input;
I'm new to developing and I've checked documentation and have found nothing. I did notice someone saying I should use a UITextField, however this doesn't suit my needs as to what i require the UILabel to display.
Maybe try setting the lineBreakMode property of the UILabel to NSLineBreakByWordWrapping, as the default value for this property is actually NSLineBreakByTruncatingTail which could explain the '...' that you're experiencing when the label has too much text. Also make sure the adjustsFontSizeToFitWidth property is set to NO.
textLabel.adjustsFontSizeToFitWidth = NO; // this is default value
textLabel.lineBreakMode = NSLineBreakByWordWrapping;
textLabel.numberOfLines = 0;
Options for UITextView that you may have not seen
UITextView * _descriptionText = [UITextView new];
[_descriptionText setTextAlignment:NSTextAlignmentLeft];
[[_descriptionText textContainer] setMaximumNumberOfLines:11];
[[_descriptionText textContainer] setLineBreakMode:NSLineBreakByTruncatingTail];
Not sure if this helps, but combining this with Bamsworlds answer should do it

How to use NSLineBreakByCharWrapping with setNumberOfLines:1 on iOS?

For example, if the text for a UILabel is: "Questions that may already have your answer", I want it to print
"Questions that may alr". I don't want to clip the last character but cut the text at that point.
I cannot use a character limit as most fonts are not monospaced. I cannot use clipping as It may cut the text at another point or it may cut that last letter "r" from any where of it.
The behaviour I want is similar to NSLineBreakByCharWrapping while numberOfLines = 0.
So, I want it to drop(wrap) that non-fitting last character but I want it to drop/wrap to a hidden space = I don't want that second line.
How can this be possible?
To get required output you need to know width of the label, which can be known by following method:
CGSize size = [string sizeWithAttributes:
#{NSFontAttributeName:
[UIFont systemFontOfSize:17.0f]}]; // iOS 7 and later
CGSize size = [string sizeWithFont: [UIFont systemFontOfSize:17.0f]]; // prior to iOS 7
set the size of your label with the above calculated size.
set the numberOfLines property to 1;
set the lineBreakMode property to NSLineBreakByCharWrapping;
UILabel *yourLbl = [[UILabel alloc] initWithFrame:CGRectMake(50, 50, size.width, 50)];
placeLbl.numberOfLines = 1;
placeLbl.lineBreakMode = NSLineBreakByCharWrapping;
In swift 3.0
labelObject.numberOfLines = 0;
labelObject.lineBreakMode = NSLineBreakMode.byCharWrapping

Set UILabel Align top is not working in the cell

I have a problem to implement the text vertical alignment inside a table cell.
What I want to do is based on the length of the text I want to display a message top aligned in side one UILabel inside a cell.
For example if the message is only one line
The text should align top:
And if there are two rows then it should look like this:
At the beginning what I can see is like this
So I have searched the web and what I found is to
use the
[label1 sizeToFit];
But the problem with that is within the table view cell it is not always necessarily called especially when I switched to and from another tab view.
Then I tried to generate the label on the fly by code, but the problem is that let alone the complicated process of setting up the font format I want. I have to manage whether the label has been inserted or not then reuse it every time cellForRowAtIndexpath is called.
And more weirdly, once I select the row. The alignment is switched from the one you see in the first picture to the third one. It also happens when I switched to a different tab view and switch back to the view.
I was wondering if anybody has encountered such issue and have a solution to the problem.
Thank you for your reply in advance.
Edit:
#βḧäṙℊặṿῗ, what you said I have tried. It successfully align the label text if there is only one line. My situation is that, since I have multiple tab views. Once I switch back and forth between tabs view. The alignment just restored to centre-vertical alignment again. It also happens when I selected the row. Any idea?
Try this
// label will use the number of lines as per content
[myLabel setNumberOfLines:0]; // VERY IMP
[myLabel sizeToFit];
EDIT:
As you have one extra condition that maximumly display two lines then you need to set setNumberOfLines: to 2
[myLabel setNumberOfLines:2];
Create UILabel+Extras and add following methods to this class.
- (void)alignTop{
CGSize fontSize = [self.text sizeWithAttributes:#{NSFontAttributeName:self.font}];
double finalHeight = fontSize.height * self.numberOfLines;
double finalWidth = self.frame.size.width; //expected width of label
CGRect rect = [self.text boundingRectWithSize:CGSizeMake(finalWidth, finalHeight) options:NSStringDrawingTruncatesLastVisibleLine attributes:#{NSFontAttributeName:self.font} context:nil];
CGSize theStringSize = rect.size;
int newLinesToPad = (finalHeight - theStringSize.height) / fontSize.height;
for(int i=0; i< newLinesToPad; i++)
self.text = [self.text stringByAppendingString:#" \n"];
}
Call this method like this..
[YOUR_LABEL alignTop];
Either You set no of Lines to be 0 like
[yourLabelObject setNumberOfLines:0];
[yourLabelObject sizeToFit];
Or
You can find the height of label at run time depending upon textString length.
Following method will return you the size(height & width) of label for length of text string.
here width is fixed and only height will change :
- (CGSize) calculateLabelHeightWith:(CGFloat)width text:(NSString*)textString andFont:(UIFont *)txtFont
{
CGSize maximumSize = CGSizeMake(width, 9999);
CGSize size = [textString sizeWithFont:txtFont
constrainedToSize:maximumSize
lineBreakMode:UILineBreakModeWordWrap];
return size;
}
Yo need to calculate frame of label each time when u r doing to set text and set frame of label
I hope this will helps you.
Might sound a bit silly but this is my approach: For any field that needs to be top aligned I fill the text up with multiple "\n"s. This causes the text to be automatically top aligned. Pretty much the same as Mehul's method above.
http://i.stack.imgur.com/8u5q4.png

UILabel not drawing multiline

I want the label below (in yellow) to be at least two lines rather one.
I've made sure to uncheck Use Autolayout in Interface Builder. When I set the numberOfLines from 0 to 2, I get two words stacked on top of each other, with the yellow background tightly fitting the words. The result is the same regardless of whether the lineBreakMode is NSLineBreakByWordWrapping or NSLineBreakByTruncatingTail. It's also the same if I set the frame of the terms Label using the result of sizeWithAttributes or not, and it's the same if I use sizeToFit or not. I've also tried making the label a UILabel rather than a subclass of UILabel, which is TTTAttributedLabel, but the result is the same.
_termsLabel.font = [UIFont systemFontOfSize:12];
_termsLabel.textColor = [UIColor grayColor];
_termsLabel.textAlignment = NSTextAlignmentCenter;
_termsLabel.lineBreakMode = NSLineBreakByWordWrapping;
_termsLabel.numberOfLines = 0;
_termsLabel.delegate = self;
_termsLabel.backgroundColor = [UIColor yellowColor];
// Terms label
NSString *termsText = [NSString stringWithFormat:#"%# %# %# %#", NSLocalizedString(#"TermsIAgree", nil),
NSLocalizedString(#"SettingsTOS", nil),
NSLocalizedString(#"LocalizedAnd", nil),
NSLocalizedString(#"SettingsPrivacyPolicy", nil)];
_termsLabel.text = termsText;
_termsLabel.linkAttributes = #{ (__bridge NSString *)kCTUnderlineStyleAttributeName : [NSNumber numberWithBool:YES]};
CGSize termsSize = [_termsLabel.text sizeWithAttributes: #{ NSFontAttributeName : _termsLabel.font}];
_termsLabel.frame = CGRectMake(65,
395,
termsSize.width, termsSize.height);
[_termsLabel addLinkToURL:[NSURL URLWithString:TOS_URL] withRange:[termsText rangeOfString:NSLocalizedString(#"SettingsTOS", nil)]];
[_termsLabel addLinkToURL:[NSURL URLWithString:PRIVACY_POLICY_URL] withRange:[termsText rangeOfString:NSLocalizedString(#"SettingsPrivacyPolicy", nil)]];
EDIT: By finding the terms text size using CGSize termsSize = [_termsLabel.text sizeWithFont:_termsLabel.font forWidth:200 lineBreakMode:NSLineBreakByWordWrapping];
Yet the height of the termsSize is then 14, resulting in just one line:
How can I get the second line? SOLUTION At this point, just add [_termsLabel sizeToFit].
If you've got static text, just set the break mode to wrap, set lines to the number you want, and adjust the label's frame in interface builder until it wraps the way you like. Of you've got dynamic text, you can use sizeToFit after setting the label's text to have it automatically adjust it's height to fit the specified width:
Set frame to max desired width
Set lines to 0
Set break mode to wrap
Call sizeToFit
Determine the maximum width of your label and try sizeWithFont:forWidth:lineBreakMode: method with this value and desired NSLineBreakMode to get the size of resulting string's bounding box.

iOS multiline label in Interface builder

How can I make a multiline UILabel in interface builder for iOS? I tried the UITextView but it didn't quite suit my needs.
How can I add multiline (text) in label?
You can use numberOfLines property which defines maximum number of lines a label can have. By default, it's 1. Setting it to 0 means the label will have unlimited lines.
You can do it in code:
textLabel.numberOfLines = 5 // for example
Or in Interface Builder:
Hit Control+Enter to add a line in UILabel in Interface Builder/Storyboard.
Thanks AppleVijay!
Also to call sizeToFit, like this:
label.lineBreakMode = UILineBreakModeWordWrap;
label.numberOfLines = 0;
[label sizeToFit];
The height will be automatically computed.
set width of label as u needed small then use IB to set line breaks to word wrap
or use with code like this
I found a solution.
One just has to add the following code:
textLabel.lineBreakMode = NSLineBreakByWordWrapping;
textLabel.numberOfLines = 0;
Set number of lines zero for dynamic text information, it will be useful when your text are varying.
Programatically (Swift 3)
var label = UILabel()
let stringValue = "iOS\nmultiline\nlabel\nin\nInterface\nbuilder"
label.text = stringValue
label.numberOfLines = 0 // Set 0, if number of lines not specified.
label.lineBreakMode = .byTruncatingTail // or .byWrappingWord
label.minimumScaleFactor = 0.8 . // It is not required but nice to have a minimum scale factor to fit text into label frame
Using Inetrface Builder
Note: It is not required to set Minimum Font Scale, but nice to have a minimum scale factor to fit text into label frame.
Number of lines is visible in IB with Plain UILabels
set lines field as 0 . It will create multiple lines as per the provided space to the label.
In iOS7 (Xcode5) you shold set the lines of UILabel to 0 for unlimited multiple input in storyboard.
The most important is to set the height of the UILabel can hold the lines of input you are going to set.
textLabel.lineBreakMode = UILineBreakModeWordWrap;
textLabel.numberOfLines = 0;
CGSize size = [[[arrNewsFeed objectAtIndex:row] objectForKey:#"c"] sizeWithFont:[UIFont systemFontOfSize:14.0] constrainedToSize:CGSizeMake(188, CGFLOAT_MAX)
lineBreakMode:NSLineBreakByTruncatingTail];
textLabel.frame = (CGRect){.origin = cell.lblNewsDescription.frame.origin, .size = size};
If you set the numberOfLines property equal to 0, the label will automatically adjust to the required number of lines of the given text.
I had been struggling with this for a long time.
I just wanted my label text to appear on the second line. But whatever I do, it would just overflow the UILabel box. For me, changing the autoresizing in size inspector worked. Simple fix.
May be someone might find it helpful who is looking for something similar.
For X-Code 7.2
-- Select UILabel
-- Attributes inspector
-- Text - Select Attributed
After this you can see some more attribute you can add into you label, in which you can also find number of Lines. Which make your label multiline.

Resources