So i've got a UITextView the contents of which are loaded in from an RTF file. I have the data detector type set to UIDataDetectorTypeLink, it looks as follows:
cell.articleView.attributedText = attrString;
cell.articleView.dataDetectorTypes = UIDataDetectorTypeLink;
cell.articleView.userInteractionEnabled = YES;
cell.articleView.selectable = YES;
My attributed string is:
NSAttributedString *attrString = [[NSAttributedString alloc] initWithData:[NSData dataWithContentsOfFile:path]
options:#{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType} documentAttributes:Nil error:nil];
In the cell the links load, they're colored blue etc, but clicking on them does nothing. Im assuming its because the Cell is intercepting the clicks, but I'm not sure how to circumvent that.
Related
I have a UITextView which has NSMutableAttributedString containing 2 links (NSAttributedString) that open up in separate web pages.
UITextView -> NSMutableAttributedString -> 2 NSAttributedString
And I have set UITextView's isAccessibilityElement property to YES
Presently, the voiceover reads the contents of the NSMutableAttributedString, but when it reads the links (NSAttributedString), it says "link" as a suffix
Is there a way for me to make the voiceover speak "link that opens in a webpage" instead of it speaking just "link"?
UITextView *textView = [[UITextView alloc] initWithFrame:CGRectZero];
NSAttributedString *link_1 = [[NSAttributedString alloc]
initWithString:#"some_string_1"
attributes:#{
NSLinkAttributeName : some_url_1
}];
NSAttributedString *link_2 = [[NSAttributedString alloc]
initWithString:#"some_string_2"
attributes:#{
NSLinkAttributeName : some_url_2
}];
NSMutableAttributedString *mainText = #"This is our hotel %1$# and these are reviews %2$#";
NSRange range_1 = [[mainText string] rangeOfString:#"%1$#"];
[mainText replaceCharactersInRange:range_1 withAttributedString:link_1];
NSRange range_2 = [[mainText string] rangeOfString:#"%2$#"];
[mainText replaceCharactersInRange:range_2 withAttributedString:link_2];
textView.attributedText = mainText;
textView.accessibilityTraits = UIAccessibilityTraitStaticText;
textView.isAccessibilityElement = YES;
I also tried using accessibilityAttributedHint and accessibilityAttributedLabel for this purpose, but it had no effect
I have a label where I am trying to put a symbol image at the start of the label and then some text after it. This works, but the symbol image never changes size. It doesn't matter what size I provide in the UIImageSymbolConfiguration, it stays small. If I take this code and put the image in a UIImageView, then the image gets larger as expected. Is there something wrong with anything I am doing here related to the symbol image configuration?
UILabel *label = [[UILabel alloc] init];
NSString *title = #"Some Text";
label.adjustsFontForContentSizeCategory = YES;
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:#" %#", title] attributes:#{
NSFontAttributeName: [UIFont preferredFontForTextStyle:UIFontTextStyleBody],
NSForegroundColorAttributeName: [UIColor labelColor]
}];
UIImageSymbolConfiguration *configuration = [UIImageSymbolConfiguration configurationWithFont:[UIFont preferredFontForTextStyle:UIFontTextStyleLargeTitle]];
UIImage *squareImage = [[UIImage systemImageNamed:#"square.fill" withConfiguration:configuration] imageWithTintColor:[UIColor systemBlueColor]];
NSTextAttachment *imageAttachment = [NSTextAttachment textAttachmentWithImage:squareImage];
[string insertAttributedString:[NSAttributedString attributedStringWithAttachment:imageAttachment] atIndex:0];
label.attributedText = string;
I stumbled upon the same issue as I was building a similar feature today. It seems that symbols work slightly differently when embedded in text attachments: it's the font set on the attributed string that determines the size, not the configuration of the symbol itself.
With this in mind, you simply need to make sure the range of the icon in the attributed string has a font set:
UIFont *font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
[string addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, 1)];
Note that you'll still need to configure the symbol if you intend to render using a different color. In this case, attributed strings will ignore the NSForegroundColorAttributeName attribute when rendering the symbol (resulting in a blank, zero-width symbol). I suspect this is because symbols have hierarchical colors, but I might be wrong.
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).
How could you achieve this effect:
Maybe some sort of NSAtributedString?
I have thought of hacky ways to just add spaces, but it needs to do it dynamically based on the width of the image.
Any ideas?
NOTE happily you can do this very easily with UITextView:
https://stackoverflow.com/a/20033752/294884
this question is about UILabel.
Add image in your label with text as below code:
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:#"Here is some text that is wrapping around like an image"];
NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init];
textAttachment.image = [UIImage imageNamed:#"first.jpg"];
NSAttributedString *attrStringWithImage = [NSAttributedString attributedStringWithAttachment:textAttachment];
[attributedString insertAttributedString:attrStringWithImage atIndex:0];
[_lbn setAttributedText:attributedString];
Your OUTPUT :
You can use an NSAttributedString with an NSTextAttachment
NSTextAttachment *attachment = [[NSTextAttachment alloc]init];
[attachment setImage:<#UIImage#>];
NSAttributedString* icon = [NSAttributedString attributedStringWithAttachment:attachment];
[attributedString insertAttributedString:icon atIndex:<#index#>];
but it will only insert the image on one line, so it wont have multiple lines down the side of it (like a newspaper article), so its only useful for small images that fit on one line (sort of like how you have it in your question i guess)
I have an NSTextAttachment with an image in a UILabel and I would like to perform a custom behaviour when clicking on this attachment.
UITextViewDelegate provides an handy method
textView:shouldInteractWithTextAttachment:inRange:
But it can only be used if I'm using UITextView.
Is there any solution if Im using UILabel?
Thanks!
The text attachment becomes part of the model and is treated like a character, so try adding a link to the range of your attachment.
Like this:
NSTextAttachment *attachment = [[NSTextAttachment alloc] initWithData:nil ofType:nil];
attachment.image = [UIImage imageNamed:#"myImage"];
NSAttributedString *imageString = [NSAttributedString attributedStringWithAttachment:attachment];
NSMutableAttributedString *mutableImageString = [imageString mutableCopy];
[mutableImageString addAttribute:NSLinkAttributeName value:#"http://stackoverflow.com" range:NSMakeRange(0, mutableImageString.length)];