Dynamically Change isAccessibilityElement - ios

I've got a bit of a weird situation. I need to have an element not be read out by VoiceOver when I use the 2 finger swipe method, but to be read when tapping on it still.
The object is part of a TableView cell, and I've given the TableView cell its own accessibilityLabel, because it contains two interactive elements, one of which doesn't actually need to be read when tapped on, so I've disabled its accessibility property.
However, my other one needs to be read still when tapped on. The issue is, it's already being read as part of the cell's accessibilityLabel, and then it is read again because it is still an accessible element. Is there any way to differentiate between why VoiceOver is reading an element? Or to dynamically change the accessibilityLabel?

You can dynamically change accessibilityLabel simply by assigning it or overriding the method on the accessible view. However, you shouldn't rely on VoiceOver respecting the change in real time.
Users can navigate via tap or swipe and expect elements to persist regardless of how they were reached. In general, I discourage clever solutions that assume how users interact with VoiceOver.
I'd encourage you to either override the cell summary to omit the label or disable accessibility on the label and leave the content in the cell summary.

Related

How can I enable VoiceOver for webview content on tableview

Normally, VoiceOver correctly reads web contents loaded with WKWebView and it is possible to read buttons and links.
However, when I added WKWebView on UITableViewCell and displayed in UITableVIew, VoiceOver could not recognize it.
According to the tableview document of apple, in order to make each content on UITableViewCell recognized by VoiceOver separately,
It is necessary to set isAccessibilityElement of cell to false and set isAccessibilityElement of view to be recognized to be true.
but if isAccesibilityElement ofWKWebView is set to true, view itself is focused and we can not recognize the inside web contents.
Also, when VoiceOver was enabled for the first time after loading the Web content, it performed strange behavior that Web content could be recognized.
I suspected the problem of VoiceOver content recognition timing, I tried running
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil)
or
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil)
after loading the web content, but it did not get a good result.
Is there a good way to handle contents in wkwebview on tableView to VoiceOver?
So, I'll explain the behavior you're seeing. Essentially, VoiceOver will only focus the first accessibility element in a tree. So any view that is an Accessibility Element will not have its children that are accessibility elements be focused.
Now as for your situation, I'm curious as to your scenario. I find it likely that you need to provide more detail. When I picture a tableview, I picture multiple WKWebViews in one view, which would be weird indeed.
The typical markup for a webview would be to just have NOTHING set as an accessibility element, and let the WebView determine which elements within are accessible. WKWebView should take care of reporting HTML content as proper native accessibility elements for you. To do anything else is going to corrupt what WKWebView is going. HOWEVER, if you have multiple webviews in one app, this may muck things up. Ultimately, if it didn't work the way I outlined (just by leaving things alone, and marking everything as "not" an accessibility element), this would be a bug, but a bug that you would have to deal with.
The solution THEN becomes overriding the UIAccessibilityContainer protocol for your webview, and providing custom feedback for it. Not ideal, would be painful. More details would help, but at least now you can understand a little more about what is going on.
Another simple solution would be, if the content in your webview is very simple, you could set accessibility element to true, and provide a description of the content for the entire webview through the accessibilityLabel, accessibilityValue and accessibilityTraits. Just be sure you catch all of the information, and that any actions are still actionable!

How can I get IndexPath of currently selected tableviewcell by voice over?

I'm using Voice Over in my application. I'm having hard time to figure out which table cell is currently selected when voice over is on. How can I know whenever user initiates single tap or navigate through any tableviewcell?
These are the things you can try:
use the UIAccessibilityFocusedElement global function
override accessibilityElementDidBecomeFocused and accessibilityElementDidLoseFocus on the cell
observe the UIAccessibilityElementFocused notification in NotificationCenter in situations where you need it (e.g. when the view controller for the table in question is showing)
Also what element will report focus will most probably depend on whether your UITableViewCell has isAccessibilityElement set to true or false.
While the above will probably help you with literally what you asked, it is also possible that your overall approach to accessibility in this situation might be wrong if you need the above information. If you share more info on the bigger picture / motivation what you are trying to achieve, it might turn out that the information about focused element might not be needed at all and that another solution is more proper.
If what you need is to add a hint for swiping, you can simply set accessibilityHint on the proper element (if you set isAccessibilityElement = true on the whole cell, then set that on the whole cell, otherwise try setting it on the label that VoiceOver reads in the cell), e.g. when you configure the cell for display (usually in tableView(_:cellForRowAt:)). In such case, you will not need to observe which element is focused, and simply let VoiceOver read hint available on that particular element/cell.

Provide summary of container like tableview with Voice Over

I'm trying to enable voice over for a tableview with a few standard cells. I've configured the cell views to have the appropriate accessibilityLabel and trait, but I'm stuck trying to implement the following behaviour:
When the table view is in focus, it should say: "Recipes List, 16 elements", then move to the first entry. I wonder how this could be accomplished?
Apple does something similar in the weather app. If Voice Over is active and you scroll to the details section (sun rise, sun set, humidity etc), it will say "Details, sun rise ...". When you tap directly onto the label however, it will say "sun rise, ..." (without "Details").
One workaround I thought of is to add the text to the first cell, but that feels a bit hacky, since the label logically belongs to the table view, not the cell.
Any suggestions?
A container and its children cannot be accessible all together (explanation here).
I think that a custom accessibility element should overlap the table view (both with the same frame) and ordering must have been setup in order to read out the new view before the first cell of the table view.
The table view is definitely not read out if its cells are accessible with VoiceOver.
This is just an assumption because I can't find the behavior you mentioned for the Apple weather app.

VoiceOver not reading UITextField subviews

I've got a few custom UITableViewCells that I'm making accessible. I'm trying to get VoiceOver to read all the subviews when the cell is tapped. From my understanding, this is something you get for free when using or sublcassing UITableViewCell (Correct me if I'm wrong on that.)
The issue is in a few of my cells. In most of my cells, everything reads correctly. However, when I tap on a cell that contains a UITextField (or subclass of UITextField) it does not read the UITextField. It will read all the other elements (except the UIButton on one cell as well,) but will skip the text fields.
Does anyone know any reasons it would not read the UITextFields? And the one UIButton? Is there something special that needs to be done for those to be read? Or something special to be done to a UITableViewCell subclass that I haven't done?
Sorry for posting no code, I'm not really sure what code would be relevant to post since I don't see anything related to accessibility at all in the code. In the storyboard, it is selected as accessible for all elements I want read, however the UITextFields seem to ignore this setting.
What you want to do is create a custom cell class, and override the accessibilityLabel property of that class. Collecting all subviews accessibility labels. I'm on a windows machine now, so pardon if this doesn't quite compile, but you should get the idea.
#implementation MyCustomCellViewClass
-(NSString*)accessibilityLabel {
NSMutableString* result = [NSMutableString new];
for (subview in [view accessibilityElementViews]) {
[result append:subview.accessibilityLabel];
}
return result;
}
By including this as a property override, rather than setting accessibility labels at all potential points that it changes, you remove the concern of future devs overriding this behavior. You also gain automatic handling of dynamic elements within these cells, as the accessibility label will simply stay in sync with the accessibility information of the subviews. You can then include this class as a parent class of any future subclasses to trivially maintain this behavior. If any of your devs are dumb enough to remove this sub class from the inheritance tree you have bigger problems to deal with!
Make sure with this approach that your cell has the correct role. Whatever the active element of the cell is (be it a tab, link, button, etc) should be the role of your super view. The other elements are just informative.
Let's say your table cell has 4 elements a label, a button, a text field, a image view. All these elements are in the contentView of your tablecell.
To make sure the voice over reads all the 4 elements in your table cell, you need to tell the voice over that your contentview contains 4 elements.You can do this by adding all the elements in your contentView to the contentView's accessibilityElements Array.
contentView.accessibilityElements=#[label,button,textField,imageView];
Then the voice over will not skip any of these 4 elements.

Monotouch.Dialog: Enable Selection in UITableView

Using MonoTouch.Dialog I create a table of values.
When the user clicks a row, the row should flash blue as per normal.
How do I enable this in MonoTouch.Dialog?
MonoTouch.Dialog supports the flashing behavior for Elements that can actually respond to events (like the StringElement when it has a tap-handler attached) or other elements that need to respond to the user's interaction.
This is done by setting the SelectionStyle property on the cell to UITableViewCellSelectionStyle.Blue
Most of the cells that do not respond to user's input have the value in MonoTouch.Dialog set to None. You can either change the source code to make it use Blue everywhere, or make sure that you are using the right Element for the right use case.
I blogged about some design patterns for building Elements recently, if you want to roll your own:
http://tirania.org/monomac/archive/2011/Jan-18.html

Resources