I'm trying to draw ellipsized text on multiple lines inside a rectangle.
For NSLineBreakByTruncatingTail, the documentation states
The line is displayed so that the beginning fits in the container and the missing text at the end of the line is indicated by an ellipsis glyph. Although this mode works for multiline text, it is more often used for single line text.
but with that mode I only get a single line:
However with NSLineBreakByWordWrapping, I don't get an ellipsis for overlong text:
Both pictures use the same code below (red background is the text drawing rectangle) and of course the same rectangle size, so 2 lines should definitely fit.
NSMutableParagraphStyle* paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
paragraphStyle.lineBreakMode = <<see above>>;
paragraphStyle.alignment = NSTextAlignmentNatural;
NSDictionary* drawingAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
[UIFont fontWithName:#"HelveticaNeue" size:36],
NSFontAttributeName,
paragraphStyle,
NSParagraphStyleAttributeName,
nil];
const CGRect rect = CGRectMake(...);
[#"I do not get ellipsized in any way" drawInRect:rect withAttributes:drawingAttributes];
Is there a way to combine ellipsizing with multiline rendering, as the documentation says? With a UILabel, I would only have to set the number of lines to something other than 1, but what about text rendering via code?
I don't understand why you are using NSMutableParagraphStyle and drawInRect, probably I'll need more information about the context you are trying to work.
But using this simple technique:
UILabel *label = [[UILabel alloc] initWithFrame:(CGRect){0,0,300,100}];
label.numberOfLines = 0;
label.backgroundColor = [UIColor redColor];
label.center = self.view.center;
label.font = [UIFont fontWithName:#"HelveticaNeue" size:36];
label.textAlignment = NSTextAlignmentNatural;
label.lineBreakMode = NSLineBreakByTruncatingTail;
label.text = #"I do not get ellipsized in any way";
[self.view addSubview:label];
You will see the following result:
My suggestion is to get rid of drawInRect in this case.
Related
Team,
I have UITextView added content of text, with font family avinar roma, I noticed there is small gap in between each word which was not consistent. How to avoid the small gap in textview text for each word.
descriptionTextView = [[UITextView alloc] initWithFrame:CGRectMake(20, titlelabel.frame.origin.y + titlelabel.frame.size.height + 5, view.frame.size.width - 40, view.frame.size.height - 150)];
descriptionTextView.backgroundColor = [UIColor clearColor];
descriptionTextView.textColor = MH_PANTONE_444;
descriptionTextView.textAlignment = NSTextAlignmentCenter;
descriptionTextView.font = [UIFont fontWithName:MH_FONT_AVENIRROMAN size:MH_SCREEN_HEIGHT/48];
descriptionTextView.text = [descriptionArray objectAtIndex:index];
descriptionTextView.editable = NO;
descriptionTextView.scrollEnabled = NO;
descriptionTextView.selectable = YES;
descriptionTextView.dataDetectorTypes = UIDataDetectorTypeAll;
Please have image attached above
University Medical Center, is not same gap with remaining text.
Setting the hyphenationFactor should fix your problem. But you have to use NSAttributedString instead of plain text:
UIFont *font = [UIFont fontWithName: MH_FONT_AVENIRROMAN size: MH_SCREEN_HEIGHT/48];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.hyphenationFactor = 1.0;
NSDictionary *attributes = #{ NSFontAttributeName:font,
NSForegroundColorAttributeName: MH_PANTONE_444;
NSParagraphStyleAttributeName: paragraphStyle };
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString: [descriptionArray objectAtIndex:index]
attributes: attributes];
descriptionTextView.attributedText = attributedText;
https://developer.apple.com/reference/uikit/nsmutableparagraphstyle/1535553-hyphenationfactor
You may have to adjust the hyphenationFactor until you get the result you want. (0.0-1.0)
I solved the same issue by setting the leftView property of the UITextField to be an empty view with the size of the padding as desired:
UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 5, 20)];
textView.leftView = paddingView;
textView.leftViewMode = UITextFieldViewModeAlways;
I had also face an issue of text alignment with custom fonts in iOS application, and that was with vertical alignment. I guess this is because of the custom font you are using in your application. But luckily there is a solution.
Every font file have some configurations about display the letter. One of the property is minLeftSideBearing for left spacing and minRightSideBearing for right spacing. I guess by changing them you can solve this spacing issue.
Follow the following link to check how to change this properties.
http://www.andyyardley.com/2012/04/24/custom-ios-fonts-and-how-to-fix-the-vertical-position-problem/
And as mention in above blog you need to install font tool. That you can download from following link.
https://developer.apple.com/download/more/?=font
Hope this might help you.
Thanks, Jay.
The dots are added automatically by the UILabel, cause of line limitation, but they get the background color of hidden truncated text:
So I have UILabel with line limit of 10 and line break mode of TruncatingTail.
I also have 2 types of attributed strings that build this UILabel content.
NSForegroundColorAttributeName, NSFontAttributeName
NSBackgroundColorAttributeName, NSForegroundColorAttributeName, NSFontAttributeName
Any idea why the UILabel is adding background color to the dots? There is text in line 12 (which is truncated) that have that background...
=Here Given Code Try it..
NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:#"test"];
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
style.lineBreakMode = NSLineBreakByTruncatingTail;
[text addAttribute:NSParagraphStyleAttributeName
value:style
range:NSMakeRange(0, text.length)];
label.attributedText = text;
It looks like your NSAttributedString styling is picking up on an instance of "Windsor" that is past the truncation point.
You could find where the truncation occurs, and then only apply the text attribute to the range of the string up to the truncation point.
See this SO answer to calculate this range.
NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
paragraph.lineBreakMode = mylabel.lineBreakMode;
NSDictionary *attributes = #{NSFontAttributeName : mylabel.font,
NSParagraphStyleAttributeName : paragraph};
CGSize constrainedSize = CGSizeMake(mylabel.bounds.size.width, NSIntegerMax);
CGRect rect = [mylabel.text boundingRectWithSize:constrainedSize
options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
attributes:attributes context:nil];
if (rect.size.height > mylabel.bounds.size.height) {
NSLog(#"TOO MUCH");
}
In my UITextView, I want certain NSRanges to be indented left and right equally and be highlighted in a specific color. I am achieving this by modifying NSMutableAttributedStrings and setting the textView.attributedText. To get the left/right indentation, I'm using NSMutableParagraphStyle - however, this is removing the highlighting (NSBackgroundColor). How can I get it such that the highlighting starts from the beginning, even with the headIndent.
// padding
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.headIndent = 5.0;
paragraphStyle.firstLineHeadIndent = 5.0;
paragraphStyle.tailIndent = -5.0;
NSDictionary *referenceAttributes = #{NSForegroundColorAttributeName: [UIColor lightGrayColor], NSBackgroundColorAttributeName: [UIColor brownColor], NSFontAttributeName: [UIFont fontWithName:#"HelveticaNeue-Bold" size: 14], NSParagraphStyleAttributeName: paragraphStyle};
Use following code to give padding in UITextView
self.textView.textContainer.lineFragmentPadding = 0;
I have a UILabel which uses an Attributed String. I want to have its line height to be exactly the size of the font size, not a pixel bigger. However, a top and bottom padding are being added. See image below:
This is my code to create the label.
NSDictionary *basicAttributes = #{NSForegroundColorAttributeName: [UIColor whiteColor], NSBackgroundColorAttributeName: [UIColor blueColor]};
NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithDictionary:basicAttributes];
UIFont *font = [UIFont fontWithName:#"AvenirNext-Regular" size:20.0];
[attributes setObject:font forKey:NSFontAttributeName];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineHeightMultiple = 1.0f;
[attributes setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];
self.helloWorldLabel.attributedText = [[NSMutableAttributedString alloc] initWithString:#"Hola" attributes:attributes];
Attempts
I have tried to call sizeToFit after setting the attributedText without success.
[self.helloWorldLabel sizeToFit];
I have played with other attributes of NSMutableParagraphStyle such as lineSpacing without success.
paragraphStyle.lineSpacing = 0.0f;
What am I missing?
Thanks in advanced
It sounds like you want to use boundingRectWithSize: Here's a short example of how to use it. This code will dynamically determine your label size based on the text in your label. Setting the constraining sizes allows a max size if content needs to overflow to multiple lines.
NSString *text = [NSString stringWithFormat:#"Title Header:%#", value];
NSRange boldRange = [text rangeOfString:#"Title Header:"];
NSRange normalRange = [text rangeOfString:value];
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:text];
//Add attributes for appropriate ranges
[attributedText setAttributes:#{ NSFontAttributeName:[UIFont fontWithName:#"HelveticaNeue-Bold" size:13.0f]} range:boldRange];
[attributedText setAttributes:#{ NSFontAttributeName:[UIFont fontWithName:#"HelveticaNeue" size:13.0f]} range:normalRange];
//Determine rect for attributed text constrained within max values
CGRect textAttributedSize = [attributedText boundingRectWithSize:CGSizeMake(CellTitleWidth, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading context:NULL];
[self.myLabel setText:attributedText];
[self.myLabel setFrame:textAttributedSize];
Check this link. There is no 100% way to correctly set the frame to fit the letters. You can calculate the attributed string with CoreText like using CTFramesetterRef CTFramesetterSuggestFrameSizeWithConstraints but it is more additional work.
For some reason, when I display the word "Butterfly" (or anything else with an "fl"), the "f" and the "l" connect at the top (see image below). The font is Century Gothic Bold. This is the code I use to setup the UILabel. The string for the label is retrieved from a plist:
UILabel *label = [[UILabel alloc] init];
label.text = [self.flashcardDelegate.alphabetArr objectAtIndex:index];
label.textColor = [UIColor colorWithRed:.733 green:0 blue:.03137 alpha:1];
label.backgroundColor = [UIColor clearColor];
label.frame = CGRectMake(ipad ? 210.0f : 65.0f,
ipad ? 650.0f : 300.0f,
ipad ? 340.0f : 185.0f,
ipad ? 250.0f : 135.0f);
label.font = [UIFont fontWithName:#"CenturyGothic-Bold" size:ipad ? 200 : 100];
label.textAlignment = UITextAlignmentCenter;
Any idea why this would happen? Thanks.
It's called a ligature, and it's intentional. You can change how the OS renders ligatures by using the kCTLigatureAttributeName attribute if you're using Core Text, or you can use NSLigatureAttributeName if you're using NSAttributedString.
What you're seeing is known as a ligature - the idea was originally to make it easier to handle the kerning on metal blocks for printing presses (to use one glyph for commonly-joined character pairs), but now has persisted into the modern era as a largely stylistic decision.
I'm unsure how to disable it in the API, but hopefully this additional background information can help you find the answer.
Here is a short way of doing this. iOS 6.0+
NSMutableAttributedString *attributedString;
attributedString = [[NSMutableAttributedString alloc] initWithString:label.text];
[attributedString addAttribute:NSLigatureAttributeName value:#0 range:NSMakeRange(0, label.text.length)];
[label.text setAttributedText:attributedString];
[attributedString release];