Accessibility : Make UILabel with Attributed text as accessibility container - ios

I have a custom view. I capture the screenshot of view and use image in NSTextAttachment as :
UIImage *image = view.image;
NSTextAttachment *attachment = [NSTextAttachment new];
attachment.image = image;
I then create a mutable Attributed string with this attachment as:
NSAttributedString *attrStr = [NSAttributedString attributedStringWithAttachment:attachment];
This code is looped for all views and one final attributed string is created by appending all attrStr's as:
[mutableString beginEditing];
[mutableString appendAttributedString:attrStr];
[mutableString endEditing];
This is then set to UILabel attributed text.
Problem : I want voice over to iterate through individual images in attributed text. So that each image is in focus by voice over.
Thanks !!

The best way to iterate through individual images (like a collection view for instance) relies on the fact to define each element as a UIAccessibilityElement inside a wrapper whose trait property is adjustable.
To understand how that should be implemented, I suggest you take a look at the WWDC 2018 - Deliver an exceptional accessibility experience video whose content is perfectly summarized here and whose presented example can be downloaded.
Use of UIAccessibilityContainer protocol could be an interesting track of investigation as well.
Finally, I don't think you could iterate your images inside the attributed text as is but creating a kind of accessible structure perfectly understandable by VoiceOver as defined before would allow to reach your goal.

Related

Change text color in specific situation

I'm using this method to change color to few chars of my UITextView
+(void)changeColorToTextObject : (UITextView *)textView ToColor : (UIColor *)color FromLocation : (int)location WithLength : (int)length
{
NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithAttributedString: textView.attributedText];
[text addAttribute:NSForegroundColorAttributeName value:color range:NSMakeRange(location, length)];
[textView setAttributedText: text];
}
It works great but after I change the specific range I want to be able to continue with the previous color and not with the new color that I just changed to.
How can I do it?
Actually, when working with attributed text, I found it best practice to set content first and style second (which actually originates from old typesetting rules).
In your case, I would first set the whole text on the UITextView, and then call the method changeColorToTextObject:ToColor:FromLocation:WithLength specifying only the portion of the text you want in a different color.
However, if you are not talking about static content, but rather something like a word processor app, where the user can change text color and continues to write afterwards, you need to think about how you want this app to work. Consider the following method:
- (void)highlightSelectedText {
UIColor *highlightColor = [UIColor redColor];
[self changeColorToTextObject:self.textView ToColor:highlightColor FromLocation:self.textView.selectedRange.location WithLength:self.textView.selectedRange.length];
}
This method allows you to highlight the specific part of the text, the user has currently selected:
If the user then continues typing, the new text will appear in red:
If instead, they put the focus at a place where font color is black, they will continue writing in black:
When you think about a word processor, that seems actually pretty familiar. And if that is good enough for you, you are good to go.
The only border case you need to worry about then is what you do, when there is no text selected.
However, if you need more control over the dynamic behavior of your UITextView (and if you are >iOS 7), you should consider using Text Kit, and in particular subclassing NSTextStorage. There is a introduction video to Text Kit from WWDC 2013, and a great tutorial by Ray Wenderlich.
Save your previous color into a 'UIColor' property before apply the attributedText to the UITextView, and assign it to the UITextView after using the 'changeColorToTextObject' method.

How to apply attribute for text in `UITextView` without setting `attributedText` property?

I'm working on editor with syntax highlighting. After each character typed i should parse the text and highlight it. The problem is that if i create NSAttributedString instance and do UITextViewinstance.attributedText = newAttrStr i have textViewDidChange: event and some reinits in UITextView and UITextStorage behind the scene.
How to apply attribute for text in UITextView without setting attributedText property?
Can i use NSMutableAttributeString for example and add/remove attributes (i believe it works if UITextView does not copy NSAttributedString instance only but it's #property(nonatomic, copy) NSAttributedString *attributedText)? Any another approach?

TextKit and VoiceOver

I've been following the iOS7 Day-by-Day multi-page TextKit tutorial, and ran into an issue with accessibility. The code for the tutorial is here: iOS7 Day-by-Day
The problem is that each of the text views (one per column, two per "page") seems to contain the entire string, and with VoiceOver enabled, every time a column gets the focus, the text is read from the very beginning of the string to the very end, instead of reading the text that is actually visible in a column.
The textviews/columns are created using the new iOS7 method
UITextView *textView = [[UITextView alloc] initWithFrame:textViewFrame
textContainer:textContainer];
How can I get VoiceOver to read only the visible text in each column?
Sounds like you simply need to determine what text is visible and then pass that to VoiceOver.
To do that, you can use the two possible methods found in this related question and with the range of the visible text, you can then create a substring via something like:
NSString *textToPassToVoiceOver = [[textView.text] rangeOfSubstring:visibleTextRange];
Makes sense?

Different Text font at each line of UIlabel

Is there any way to give different font size to each line of a label with "n" no of lines.
I dont want to take multiple labels for this purpose.
plz help!!!
Starting with iOS 6, you can use NSAttributedString in UILabel.
An NSAttributedString object manages character strings and associated sets of attributes (for example, font and kerning) that apply to individual characters or ranges of characters in the string.
NSMutableAttributedString *attrStr = ...
myLabel.attributedText = attrStr;
Yes, but You have to use UIWebView, pass your text in html format.
UILabel with NSAttributedString(iOS 6 and later).
Or UIWebView with html-strings, but my favorit is a UITextView with html-strings. You can use it like this:
UITextView *tView=[UITextView new];
[tView setValue:#"<b>foo</b>bar" forKey:#"contentToHTMLString"];
UITextViews are easier to handle then UIWebView, especially if you don't need all the functionality of the WebView.
If you are targeting iOS < 6.0 then by using UILabel its not at all possible. Else you can refer dasblinkenlight answer (for iOS > 6)
There are couple of methods by which you can implement same :
Use UIWebView
Create UILabel for different fonts you want and set their frame as you want to display.

How to change shape of the UITextField?

I want to implement custom text fields. Here is a screenshot of what I want to implement:
So I have a UITableView with cells, and in each cell I have several text fields: one for date, one for name, one for theme, and one for text. But the UI requires theme and text to be next to each other (as can you see in the picture). I wanted to implement this as a single UITextField, but as far as I know, UITextField supports only one type of font. So maybe someone will give me a piece of advice how to implement the design shown in the screenshot — do I have to draw custom text fields, or are there simpler solutions? Any code samples or propositions would be helpful.
For iOS 6:
You can set a UITextField's attributed string:
#property(nonatomic,copy) NSAttributedString *attributedText;
I suggest to use a NSMutableAttributedString and to exploit polymorphism.
A mutable attributed string can hold vary attributes for each piece of the string. So you can add an attribute only for a certain range of the string with this method:
- (void)setAttributes:(NSDictionary *)attributes range:(NSRange)aRange;
For iOS 5:
Use directly this UITextField's property:
- (void)setAttributes:(NSDictionary *)attributes range:(NSRange)aRange;

Resources