Goal is to have a single NSAttributedString with a larger line height between paragraphs than within a paragraph, a fairly simple and common use case it seems to me. Here's my code:
NSMutableParagraphStyle *firstParagraphStyle = [[NSMutableParagraphStyle alloc] init];
firstParagraphStyle.lineHeightMultiple = 3.0;
NSMutableParagraphStyle *secondParagraphStyle = [[NSMutableParagraphStyle alloc] init];
secondParagraphStyle.lineHeightMultiple = 1.0;
NSAttributedString *title = [[NSAttributedString alloc] initWithString:#"Title"
attributes:#{NSParagraphStyleAttributeName: firstParagraphStyle}];
NSAttributedString *bodyTop = [[NSAttributedString alloc] initWithString:#"\u2029Body 1"
attributes:#{NSParagraphStyleAttributeName: secondParagraphStyle}];
NSAttributedString *bodyBottom = [[NSAttributedString alloc] initWithString:#"\u2029Body 2 line 1\u2028Body 2 line 2"
attributes:#{NSParagraphStyleAttributeName: secondParagraphStyle}];
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] init];
[attributedString appendAttributedString:title];
[attributedString appendAttributedString:bodyTop];
[attributedString appendAttributedString:bodyBottom];
All four lines end up with the same line spacing of 3.0. In fact, when I remove the attributes dictionary entirely and simply do:
NSAttributedString *title = [[NSAttributedString alloc] initWithString:#"Title"];
NSAttributedString *bodyTop = [[NSAttributedString alloc] initWithString:#"\u2029Body 1"];
NSAttributedString *bodyBottom = [[NSAttributedString alloc] initWithString:#"\u2029Body 2 line 1\u2028Body 2 line 2"];
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] init];
[attributedString appendAttributedString:title];
[attributedString appendAttributedString:bodyTop];
[attributedString appendAttributedString:bodyBottom];
[attributedString addAttribute:NSParagraphStyleAttributeName
value:firstParagraphStyle
range:NSMakeRange(0, 1)];
[attributedString addAttribute:NSParagraphStyleAttributeName
value:secondParagraphStyle
range:NSMakeRange(1, attributedString.length - 1)];
it still renders all three paragraphs using line height multiple of 3.0. It seems that whatever the first paragraph style I apply to the string is, that's the one that applies to all subsequent lines and paragraphs!
Why doesn't using the special paragraph separator character \u2029 as Apple suggests here allow for more than one paragraph style within a single NSAttributedString? I'd prefer not to break into multiple UILabels.
Thanks in advance to anyone with deep Core Text knowledge on this subject.
Ended up getting this working. Turns out when I set alignment on the subsequent UILabel to .textAlignment = NSTextAlignmentCenter that messed up the paragraph style for the entire attributedText.
So the lesson is: If you're using multiple paragraph styles, don't set any corresponding properties on the UILabel or your behavior will be clobbered by the first paragraph style the label sees, even when the properties aren't related (e.g. line height and text alignment).
Related
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");
}
label text first line need to indent,I use NSMutableParagraphStyle setFirstLineHeadIndent.
But when the label is only one line, AttributedString intercept omitted behind a few characters,why?
NSMutableParagraphStyle *style = [NSMutableParagraphStyle new];
[style setFirstLineHeadIndent:11];
[[NSAttributedString alloc] initWithString:#"abcdefg" attributes:dic];
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
I am attempting to have a multiline NSAttributedString, with a line spacing of 1.25.
NSMutableParagraphStyle *bodyFormat = [[NSMutableParagraphStyle alloc] init];
bodyFormat.alignment = NSTextAlignmentLeft;
//[bodyFormat setLineSpacing:5];
[bodyFormat setLineBreakMode:NSLineBreakByWordWrapping];
//[bodyFormat setMaximumLineHeight:5];
[bodyFormat setLineHeightMultiple:1.25];
NSMutableAttributedString *desc = [[NSMutableAttributedString alloc] initWithString:#"So why to use Lorem Ipsum and why placeholder text is necessary? Naturally, page designs that are made for text documents must contain some text rather than placeholder dots or something else. Howevr, should they contain a proper English words and sentenses almost every reader will deliberately try to interpret it eventually missing the design itself"];
[desc addAttribute:NSParagraphStyleAttributeName value:bodyFormat range:NSMakeRange(0, desc.length)];
UILabel *description = [[UILabel alloc] initWithFrame:CGRectMake(0,
20,
300,
1000)];
description.lineBreakMode = NSLineBreakByWordWrapping;
[description setAttributedText:desc];
[self.view addSubview:description];
This manages to produce a single line, and the linebreak is not effective.
What am I doing wrong?
[bodyFormat setLineSpacing:5];
breaks this behavior.
Also setting
description.numberOfLines = 0;
helps... (description is the UILabel)
In the UITextView text,
before highlight the text, its shown the text size as 16. (in the first image)
after the using the NSAttributedString to highlight. highlighted text only show that same size(16) remaining strings show lesser than that the original size (second .
this problem only in the iPod and iPhone deceive . iPad is shown correct format.
code to highlight the UITextView Text
NSDictionary *attrsDictionary = [NSDictionary dictionaryWithObject:[UIFont fontWithName:#"Arial" size:currentTextSize] forKey:NSFontAttributeName];
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:txtview4disp.text];
int startind=[[dict objectForKey:#"BeginIndexPos"]integerValue];
int endind=[[dict objectForKey:#"EndIndexPos"]integerValue];
NSRange rang;
if (startind>=STARTINDEX&&startind<=ENDINDEX) {
if (endind>ENDINDEX) {
int endind2=endind-ENDINDEX;
rang=NSMakeRange(startind-STARTINDEX, (endind-startind)-endind2);
}
else
rang=NSMakeRange(startind-STARTINDEX, endind-startind);
[attrString addAttributes:attrsDictionary range:rang];
[attrString addAttribute:NSBackgroundColorAttributeName value:[UIColor yellowColor] range:rang];
txtview4disp.attributedText=attrString;
It looks like you skipped the original attributes of your UITextView.
Try replacing this line:
NSMutableAttributedString *attrString =
[[NSMutableAttributedString alloc] initWithString:txtview4disp.text];
with following:
NSMutableAttributedString *attrString =
[[NSMutableAttributedString alloc] initWithAttributedString:txtview4disp.attributedText];