Modifying the width of an underline using attributed text? - ios

Is there a a way to modify the line width of the underline an NSAttributedString?
It seems I can easily modify the color but I can't modify the width of the underline itself easily.

You can set NSUnderlineStyleThick or NSUnderlineStyleSingle, eg:
NSAttributedString *str = [[NSAttributedString alloc] initWithString:#"Thick underline" attributes:#{NSUnderlineStyleAttributeName: #(NSUnderlineStyleThick)}];
NSAttributedString *str = [[NSAttributedString alloc] initWithString:#"Normal underline" attributes:#{NSUnderlineStyleAttributeName: #(NSUnderlineStyleSingle)}];
Full list of underline styles here: https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/NSAttributedString_UIKit_Additions/index.html#//apple_ref/c/tdef/NSUnderlineStyle

// assume Label name as "label"
// underline code
CGSize expectedLabelSize = [#"Some text" sizeWithFont:label.font constrainedToSize:label.frame.size lineBreakMode:UILineBreakModeWordWrap];
UIView *viewForUnderline=[[UIView alloc] init];
viewForUnderline.frame=CGRectMake((label.frame.size.width - expectedLabelSize.width)/2, expectedLabelSize.height + (label.frame.size.height - expectedLabelSize.height)/2, expectedLabelSize.width, 1);
viewForUnderline.backgroundColor=[UIColor whiteColor];
[self.view addSubview:viewForUnderline];
or you can use following line of code
label.attributedText = [[NSAttributedString alloc] initWithString:#"Some Text"
attributes:underlineAttribute];

Related

UILabel with multiple chained NSAttributedString, with line limit, show the tail truncation with NSBackgroundColorAttributeName of unseen text

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");
}

Chinese characters interline spacing in UITextView

I have translated an app into Simplified Chinese.
The app is using a UITextView and the contents of it is Simplified Chinese text.
I have noticed that (sometimes not always) the interline spacing is wrong, the lines are practically touching each other :
I am setting the contents of the UITextview via an attributed string that I create based on a required pointsize like this:
-(NSMutableAttributedString*) textWithPointSize:(CGFloat)pointSize
{
UIFont * myFontDescr = [UIFont systemFontOfSize:pointSize];
NSMutableAttributedString * description = [[NSMutableAttributedString alloc] initWithString:self.exercise.descr attributes:#{NSFontAttributeName:myFontDescr}];
UIFont * myFontTips = [UIFont italicSystemFontOfSize:pointSize];
NSMutableAttributedString * tips = [[NSMutableAttributedString alloc] initWithString:self.exercise.tips attributes:#{NSFontAttributeName:myFontTips}];
NSMutableAttributedString * text = [[NSMutableAttributedString alloc] initWithAttributedString:description];
[text appendAttributedString:[[NSAttributedString alloc] initWithString:#"\n\n"]];
[text appendAttributedString:tips];
return text;
}
I am using the systemFontOfSize: function, I guess this should handle Chinese characters correctly? Any ideas why this could be happening?
I did not find out why but I implemented a work around by explicitly setting the interline spacing (only when language is Chinese) like this:
//for chinese language we have detected a problem with the interline spacing
//it does happen randomly, and so to workaround this we set the linespacing explicitly
if ( [NSLocalizedString(#"__CurrentLanguage",#"zh-Hans") isEqualToString:#"zh-Hans"] ) {
//make paragraph styl with interline spacing
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = 0.25 * pointSize;
//font for description
UIFont * myFontDescr = [UIFont systemFontOfSize:pointSize];
NSMutableAttributedString * description = [[NSMutableAttributedString alloc] initWithString:self.exercise.descr attributes:#{NSFontAttributeName:myFontDescr, NSParagraphStyleAttributeName:paragraphStyle}];
//font for tips
UIFont * myFontTips = [UIFont italicSystemFontOfSize:pointSize];
NSMutableAttributedString * tips = [[NSMutableAttributedString alloc] initWithString:self.exercise.tips attributes:#{NSFontAttributeName:myFontTips,NSParagraphStyleAttributeName:paragraphStyle}];
//add description then...
NSMutableAttributedString * text = [[NSMutableAttributedString alloc] initWithAttributedString:description];
//concat the tips (with 2x newline in between)
[text appendAttributedString:[[NSAttributedString alloc] initWithString:#"\n\n"]];
[text appendAttributedString:tips];
//return value
return text;
}
//its not chinese, so do "normal" stuff

How to set correctly the line height of UILabel with an AttributedString?

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.

UILabel won't register line spacing property

For some reason this code (the bold text in particular) doesn't change the line spacing of the text at all:
UIFont* customFont = [UIFont fontWithName:#"BebasNeue" size:70];
NSString * text = #"Their \nIdeas";
**NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:text];
NSMutableParagraphStyle *paragrahStyle = [[NSMutableParagraphStyle alloc] init];
paragrahStyle.lineSpacing = 30;
[attributedString addAttribute:NSParagraphStyleAttributeName value:paragrahStyle range:NSMakeRange(0, [text length])];**
UILabel *lbl1 = [[UILabel alloc] init];
[lbl1 setFrame:CGRectMake(120, 70, viewWidth, 180)];
lbl1.backgroundColor = [UIColor clearColor];
lbl1.textColor = grayColor;
lbl1.numberOfLines = 2;
lbl1.attributedText = attributedString;
lbl1.userInteractionEnabled = NO;
lbl1.text = text;
[lbl1 setFont:customFont];
[view addSubview:lbl1];
[lbl1 setTransform:CGAffineTransformMakeRotation(0.35)];
What am I doing wrong?
The issue is with this line ,
lbl1.text = text;
You are assigning a non attributed string just after assigning the attributed string which contains all line spacing data. Remove above line then your code will work.
And if you are using a large value for line spacing, make sure your label's height is enough to display the second line.

Use sizeToFit with lineSpacing

I have a UILabel with several lines. The text is set dynamically, and my label height too, with this native method :
[myLabel sizeToFit];
I have an other method that sets the line spacing in my label :
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:#"My long dynamic text"];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setLineSpacing:5];
[attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [labelText length])];
myLabel.attributedText = attributedString;
The problem is that even if I set the line spacing first, and then call sizeToFit, the new height of my label is to small. It doesn't take in count the line spacing.
It really is a problem as my label is in a UIScrollView and I need the right height.
For getting size of label dynamically based on text length use this method:
/*! Returns the size of the label to display the text provided
#param text
The string to be displayed
#param width
The width required for displaying the string
#param fontName
The font name for the label
#param fontSize
The font size for the label
*/
- (CGSize)getSizeForText:(NSString *)text maxWidth:(CGFloat)width font:(NSString *)fontName fontSize:(float)fontSize {
CGSize constraintSize;
constraintSize.height = MAXFLOAT;
constraintSize.width = width;
NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
[UIFont fontWithName:fontName size:fontSize], NSFontAttributeName,
nil];
CGRect frame = [text boundingRectWithSize:constraintSize
options:NSStringDrawingUsesLineFragmentOrigin
attributes:attributesDictionary
context:nil];
CGSize stringSize = frame.size;
return stringSize;
}
Try using – boundingRectWithSize:options:context: method of the NSMutableAttributedString. Refer the Apple Docs for more info.

Resources