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
Related
I've got an app that displays Greek text. I use the Cardo font for good display. In working on an AppleWatch extension and app, it was pointed out to me that some of the special characters are being cut off. This is how some example text should look (screenshot from an iPhone simulator):
Here is the same text on the Watch simulator:
Note that the fancy accent character (to be specific, a breathing mark with a circumflex accent) on the second character of the first word is cut off. I tried setting the label's frame on the phone using some NSString measuring code like this:
UILabel *label = [[UILabel alloc]init];
label.font = [UIFont fontWithName:#"Cardo" size:16];
[self.view addSubview:label];
label.text = #"οὗτος ἦλθεν εἰς μαρτυρίαν ἵνα μαρτυρήσῃ περὶ τοῦ φωτός, ἵνα πάντες πιστεύσωσιν δι᾽ αὐτοῦ.";
label.numberOfLines = 0;
label.lineBreakMode = NSLineBreakByWordWrapping;
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc]init];
style.lineBreakMode = NSLineBreakByWordWrapping;
CGRect rect = [label.text boundingRectWithSize:self.view.bounds.size
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName: label.font,
NSParagraphStyleAttributeName: style} context:nil];
label.frame = CGRectMake(5, 100, ceilf(rect.size.width), ceilf(rect.size.height));
label.layer.borderWidth = 1; //for clarity
label.layer.borderColor = [UIColor blackColor].CGColor;
The result looks like this (the border is drawn for clarity's sake):
Interestingly, if I use the system font instead of Cardo, the extra symbols display correctly:
So, my question: What causes the NSString sizing to cut off the extra marks? Is there some option I can pass to the sizing method to correct this? Or better yet, is there some option I can set on the WKInterfaceLabel in the Watch app to get it to render correctly?
I don't know if this will fix it or not, but this will give you more to look into. I ran into an issue with a font using "Lower Case" numbers, which is a typography style for tabular numbers. I was able to create a variation of the font using a UIFontDescription that forced all numbers to be upper case. In your case the font's ascenders go over the top of the font's capHeight. There are a bunch of options for creating a font using a font descriptor and one of them may help. Here is how I created the upper case number font.
_font = [UIFont fontWithName:_fontName size:size];
NSArray* featureSettings = #[
#{
UIFontFeatureTypeIdentifierKey: #(kNumberCaseType),
UIFontFeatureSelectorIdentifierKey: #(kUpperCaseNumbersSelector)
}];
UIFontDescriptor* originalDescriptor = [_font fontDescriptor];
UIFontDescriptor* newDescriptor = [originalDescriptor fontDescriptorByAddingAttributes: #{UIFontDescriptorFeatureSettingsAttribute: featureSettings }];
_font = [UIFont fontWithDescriptor: newDescriptor size: size];
Specifically check out the kVerticalPositionType.
I actually ran into a case in my iOS app where the font ascenders where going over the capHeight from the baseline up and my attributed string was getting cut off. Since I was in quartz drawing code I just use the difference of the font's lineHeight with its ascender and padded the top. Unfortunately that is not an option on the Apple Watch.
I suspect the problem is in the font itself, with the ascenders being set too tightly for proper display.
I would first try setting the UILabel's text inset by making a subclass of UILabel and overriding drawTextInRect:
- (void)drawTextInRect:(CGRect)rect {
UIEdgeInsets insets = {5, 0, 0, 0};
[super drawTextInRect:UIEdgeInsetsInsetRect(rect, insets)];
}
If you have tried increasing the text inset to accommodate the font and it has not worked, take a look at Custom installed font not displayed correctly in UILabel
I have a UILabel that I need to convert to a UITextView because reasons. When I do this, the text is not positioned the same, despite using the same (custom) font.
I found that if I set:
textView.textContainer.lineFragmentPadding = 0;
textView.textContainerInset = UIEdgeInsetsZero;
This gets the text very close, but if I superimpose the UITextView over top of the UILabel, I see the text positioning get farther apart with each new line.
The UILabel is green, the UITextView is black. This is using NSParagraphStyle to set min and max line height to 15.
I've played with setting the paragraph style and min/max line height, but I haven't been able to match it exactly. I'm not a printer, so I don't necessarily understand all of the font related terms in the documentation for NSLayoutManager and NSTextContainer and all that.
I only need to support iOS 7 and up.
I'm not going to switch to some crazy CoreText-based custom widget or use some random third party library. I'm okay with close enough if I have to. But it seems like there should be some combination of random properties to make them layout the same.
I took the solution for line spacing found at this link and applied it to your issue. I managed to get it incredibly close by adjusting the lineSpacing property. I tested with HelveticaNeue size 13 and managed to get it to line up as shown in the screen shot below.
textView.textContainer.lineFragmentPadding = 0;
textView.textContainerInset = UIEdgeInsetsZero;
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = -0.38;
NSDictionary *attrsDictionary =
#{ NSFontAttributeName: [UIFont fontWithName:#"HelveticaNeue" size:13.0f],
NSParagraphStyleAttributeName: paragraphStyle};
textView.attributedText = [[NSAttributedString alloc] initWithString:textView.text attributes:attrsDictionary];
I've been able to successfully 'impersonate' a non-editable multiline UILabel (as it happens, in a UITableViewCell subclass) with an equivalent editable multiline UITextView using the following :
_textView = UITextView.new;
_textView.font = _label.font;
_textView.textColor = _label.textColor;
_textView.textAlignment = _label.textAlignment;
_textView.backgroundColor = UIColor.clearColor;
_textView.textContainer.lineFragmentPadding = 0;
_textView.textContainerInset = UIEdgeInsetsZero;
and to make it behave well when doing actual edits, add the following to your UITextViewDelegate:
- (void)textViewDidChange:(UITextView *)textView
{
...
[textView scrollRangeToVisible:NSMakeRange(textView.text.length, 0)];
[textView scrollRectToVisible:[textView caretRectForPosition:textView.endOfDocument] animated:NO];
}
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.
I am trying to set attribute text to a label. The attributes seems to be a working the font as well as the color.
Only issue I am facing is the wrapping of lines. The Size of the UILabel is (200,300) with numberofLines=0. So with this it should wrap the lines, but it is not happening so.
NSMutableString *title=[[NSMutableString alloc] init];
NSRange range1;
NSRange range2;
NSRange range3;
NSString *str1=#"ABCD EFGHI klm";
[title appendString:str1];
range1=NSMakeRange(0, str1.length);
NSString *str2=#"PQRSSSS ";
[title appendString:str2];
range2=NSMakeRange(range1.length, str2.length);
NSString *str3=#"1235 2347 989034 023490234 90";
[title appendString:str3];
range3=NSMakeRange(range2.location+range2.length, str3.length);
NSMutableAttributedString *attributeText=[[NSMutableAttributedString alloc] initWithString:title];
[attributeText setAttributes:[NSDictionary dictionaryWithObjectsAndKeys:color1,NSForegroundColorAttributeName,[self getStlylishItalicFont:13.0] ,NSFontAttributeName,nil] range:range1];
[attributeText setAttributes:[NSDictionary dictionaryWithObjectsAndKeys:color2,NSForegroundColorAttributeName,[self getStylishFont:13.0] ,NSFontAttributeName,nil] range:range2];
[attributeText setAttributes:[NSDictionary dictionaryWithObjectsAndKeys:color3,NSForegroundColorAttributeName,[self getStylishBoldFont:13.0] ,NSFontAttributeName,nil] range:range3];
self.myTextLabel.attributedText=attributeText;
UILabel is displayed like this, even though the height is 300.
ABCD EFGHI klm PQRSSSS 1235 234 ...
What you need is the NSParagraphStyle attribute :
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
paragraphStyle.alignment = NSTextAlignmentLeft;
paragraphStyle.lineSpacing = 1;
//Now add this to your attributes dictionary for the key NSParagraphStyleAttributeName eg,
#{NSParagraphStyleAttributeName:paragraphStyle,...}
On an unrelated note you know its better to create dictionaries in the modern Objective-c format. Whenever I don't, my mentor get's angry. That would look something like this :
[attributeText setAttributes:#{NSForegroundColorAttributeName:color1, NSFontAttributeName:[self getStlylishItalicFont:13.0], NSParagraphStyleAttributeName:paragraphStyle, }];
//The trailing comma in the dictionary definition is not at typo it is important.
Make sure you set your UILabel's line break mode attribute to the one you desired like so:
UILabel.lineBreakMode = NSLineBreakByWordWrapping;
Or if you are using Interface Builder, you can do it there.
Why can't you set the numberoflines to 1.Because wrapping makes sense but number of lines 0 doesnt make sense.. and also you have to set proper frame for label.
I think so u are facing the problem with the uilabel increasing the height , If u need the multiple lines in label then u have to give the property of havin numberoflines=0; after that u have to resize the label frame according to the size of text u are giving to the label.
Please check the below code i may be useful to u,
NSString *someText = [NSString stringWithFormat:#"%#",[[arrFulldetails objectAtIndex:indexPath.row]valueForKey:#"MessageText"]];
CGSize constraintSize;
constraintSize.width = 300.0f;
constraintSize.height =100000;
CGSize stringSize =[someText sizeWithFont: [UIFont boldSystemFontOfSize: 17] constrainedToSize: constraintSize lineBreakMode: UILineBreakModeWordWrap];
CGRect rect ;
rect = CGRectMake(10, 150, 210, 20+stringSize.height);
along with setting:
self.myTextLabel.lineBreakMode = NSLineBreakByWordWrapping;
self.myTextLabel.numberOfLines = 0;
You might also need to set your label's layout constraints to it's superview. I ran into this when I neglected to pin my label's trailing constraint to the my label's superview.
Let see that I have a string look like this:
NSString *longStr = #"AAAAA\nBBBBB\nCCCCC";
How do I make it so that the UILabel display the message like this
AAAAA
BBBBB
CCCCC
I don't think \n is recognized by UILabel, so is there anything that I can put inside NSString so that UILabel knows that it has to create a line break there?
Use \n as you are using in your string.
Set numberOfLines to 0 to allow for any number of lines.
label.numberOfLines = 0;
Update the label frame to match the size of the text using sizeWithFont:. If you don't do this your text will be vertically centered or cut off.
UILabel *label; // set frame to largest size you want
...
CGSize labelSize = [label.text sizeWithFont:label.font
constrainedToSize:label.frame.size
lineBreakMode:label.lineBreakMode];
label.frame = CGRectMake(
label.frame.origin.x, label.frame.origin.y,
label.frame.size.width, labelSize.height);
Update : Replacement for deprecatedsizeWithFont:constrainedToSize:lineBreakMode:
Reference, Replacement for deprecated sizeWithFont: in iOS 7?
CGSize labelSize = [label.text sizeWithAttributes:#{NSFontAttributeName:label.font}];
label.frame = CGRectMake(
label.frame.origin.x, label.frame.origin.y,
label.frame.size.width, labelSize.height);
Use option-return when typing in the little box in Interface Builder to insert a line feed (\n). In Interface Builder's Label attributes, set # Lines = 0.
Select the label and then change Lines property to 0 like in the above image, and then use \n in your string for line break.
In the interface builder, you can use Ctrl + Enter to insert /n to the position you want.
This way could implement the following situation
aaaaaaaaaa
If you read a string from an XML file, the line break \n in this string will not work in UILabel text. The \n is not parsed to a line break.
Here is a little trick to solve this issue:
// correct next line \n in string from XML file
NSString *myNewLineStr = #"\n";
myLabelText = [myLabelText stringByReplacingOccurrencesOfString:#"\\n" withString:myNewLineStr];
myLabel.text = myLabelText;
So you have to replace the unparsed \n part in your string by a parsed \n in a hardcoded NSString.
Here are my other label settings:
myLabel.numberOfLines = 0;
myLabel.backgroundColor = [UIColor lightGrayColor];
myLabel.textColor = [UIColor redColor];
myLabel.font = [UIFont fontWithName:#"Helvetica Neue" size:14.0];
myLabel.textAlignment = UITextAlignmentCenter;
Most important is to set numberOfLines to 0 (= unlimited number of lines in label).
No idea why Apple has chosen to not parse \n in strings read from XML?
You have to set the numberOfLines property on the UILabel. The default is 1, if you set it to 0 it will remove all limits.
Important to note it's \n (backslash) rather than /n.
For those of you who want an easy solution, do the following in the text Label input box in Interface Builder:
Make sure your number of lines is set to 0.
Alt + Enter
(Alt is your option key)
Cheers!
In Swift 2.2, > iOS 8
I've set Lines = 0 on Storyboard, under Attribute Inspector and linked a referencing outlet to the label. Then use in controller like this:
#IBOutlet weak var listLabel: UILabel!
override func viewDidLoad() {
...
listLabel.text = "Line 1\nLine 2\nLine 3\nLine 4\nLine 5\nLine 6\nLine 7\nLine 8"
}
In xCode 11, Swift 5 the \n works fine, try the below code:
textlabel.numberOfLines = 0
textlabel.text = "This is line one \n This is line two \n This is line three"
Just do it like this
NSString * strCheck = #"A\nB";
strCheck = [strCheck stringByReplacingOccurrencesOfString:#"\\n" withString:#"\n"]; //This is to prevent for fetching string from plist or data structure
label.numberOfLines = 0;
label.lineBreakMode = NSLineBreakByWordWrapping;
label.text = strCheck;
// DO not forget to set numberOfLines to zero
UILabel* locationTitle = [[UILabel alloc] initWithFrame:CGRectMake(5, 30, 230, 40)];
locationTitle.font = [UIFont systemFontOfSize:13.0];
locationTitle.numberOfLines = 0;
locationTitle.text = [NSString stringWithFormat:#"Eaton industries pvt. Ltd \nUK Apr 12"];
[cell addSubview:locationTitle];
If your using a UILabel you have to remember that the default setting is 1 line, so it does not matter how many breaks you add (\n or \r), you need to make sure it is set to more than one line so it could be allowed to append more lines.
One alternative is to use UITextView which is really meant for multilines.
You can easily achieve this in XCode attribute section of the UILabel, see screenshot:
On Xcode 6, you can just use \n even inside a string when using word wrap. It will work. So for example:
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(0, 100, screenRect.size.width, 50)];
label.textAlignment = NSTextAlignmentCenter;
label.text = #"This will be on the first line\nfollowed by a line under it.";
label.lineBreakMode = UILineBreakModeWordWrap;
label.numberOfLines = 0;
In my case also \n was not working, I fixed issue by keeping number of lines to 0 and copied and pasted the text with new line itself for example instead of Hello \n World i pasted
Hello
World
in the interface builder.
Just using label.numberOfLines = 0;
textLabel.text = #"\nAAAAA\nBBBBB\nCCCCC";
textLabel.numberOfLines = 3; \\As you want - AAAAA\nBBBBB\nCCCCC
textLabel.lineBreakMode = UILineBreakModeWordWrap;
NSLog(#"The textLabel text is - %#",textLabel.text);
For anyone else that might have trouble with sizeWithFont:constrainedToSize:lineBreakMode: or anyone switching to ios8 (the method is deprecated as of ios7), I adjusted my height by using sizeToFit instead.
UILabel *label;
label.numberOfLines = 0;
// Setup label with desired settings
...
[label sizeToFit];
label.frame = CGRectMake(label.frame.origin.x, // Or use any desired origin
label.frame.origin.y,
label.frame.size.width, // Or use any desired width
label.frame.size.height);
NSCharacterSet *charSet = NSCharacterSet.newlineCharacterSet;
NSString *formatted = [[unformatted componentsSeparatedByCharactersInSet:charSet] componentsJoinedByString:#"\n"];
It seems wrong to me to change the label frame sizes especially when using autolayout. Using the appendFormat method seems more appropriate. Here is my example:
NSMutableString *list = [[NSMutableString alloc] init];
NSArray *textArray = #[#"AAAA", #"BBBB"];
for (NSString *string in textArray) {
[list appendFormat:#"%#\n", string.mutableCopy];
}
self.label.text = list;
self.label.numberOfLines = 0;
If you set your UILable properties from Plain to Attributed...the UILabel will hold multiline text no matter how many paragraphs for along as your UILabel height and width are set to fit the screen area you want to display the text in.
I have faced same problem, and here is, how i solved the problem. Hope this will be helpful for someone.
// Swift 2
lblMultiline.lineBreakMode = .ByWordWrapping // or use NSLineBreakMode.ByWordWrapping
lblMultiline.numberOfLines = 0
// Objective-C
lblMultiline.lineBreakMode = NSLineBreakByWordWrapping;
lblMultiline.numberOfLines = 0;
// C# (Xamarin.iOS)
lblMultiline.LineBreakMode = UILineBreakMode.WordWrap;
lblMultiline.Lines = 0;
on Xcode 6, I can use \n without problem on swift programmatically