When I set isAccessibilityElement = NO on a view that contains subviews with isAccessibilityElement = YES, VoiceOver still detects them.
I need to switch off accessibility for an entire view hierarchy that must be handled differently by VoiceOver. How can I achieve this without having to loop through every single item in the object graph and mess with it's setting?
self.accessibilityElementsHidden = YES;
This makes all subviews hidden from accessibility.
I would try setting the accessibilityElementsHidden property of the main view to YES. If that does not what you want, I would try overriding the UIAccessibilityContainer methods on the main view to return 0 children.
Just set the accessibilityElementsHidden property.
Related
So I've created a ViewControl in my storyboard that has 3 subviews. Each one represents a different view I want to show depending on which table row was selected on the previous screen (NavControl). I start with all of the subviews hidden via the Attributes Inspector's 'hidden' attribute being checked. All of the objects within each of these views are NOT hidden, but are being hidden because the subview itself is hidden (obviously). Thinking I could use the tag attribute I've given each of the three subviews a tag (0, 1 and 2), but can't figure out how to use that either (just in case this is useful as providing me with an option of how to do this I wanted to mention it here).
So, how the heck do I show and then hide any of these subviews? I don't want to go through each object in a subview and toggle its hidden property to true/false I feel like I should just be able to 'show/hide' the entire subview. thus achieving the same result, but much more succinctly.
I can't find anything that will help me via web searches or stackoverflow searches.
My code is very simple. I capture the row that was selected in the previous screen and pass it to a variable on the details screen that contains the subviews. I know this is working because I've set up println()'s on the details screens viewDidLoad function. So now all I have to do is going into each of these conditions and tell it which subview to show and/or hide.
Thanks I appreciate all of this communities help! I'd be lost without it.
Use this to hide a view in swift
viewVar.isHidden = true
You should create IBOutlets for each of the three subviews. Then you can show/hide each of them directly from those references. If you hide a view, it will automatically hide its subviews.
Once you have an outlet for the view, you can do this:
viewYouWantToHide.isHidden = true
If you have tags for each view you can hide and display them using:
Objective C
For Hiding:
[[self.view viewWithTag:1] setHidden:YES];
Showing:
[[self.view viewWithTag:1] setHidden:NO];
In Swift:
Hiding:
self.view.viewWithTag(1)?.isHidden = true
Showing:
self.view.viewWithTag(1)?.isHidden = false
NOTE: Replace 1 with your tag value.
however the fact that isHidden is a naming convention for checking the status and is a getter method
but despite that fact in swift we use it as setter and getter property
view.isHidden = true
I want to make a textfield and a subview on the text field accessible by VoiceOver. If I use UIAccessibilityContainer methods, I can only make the subviews accessible. Is there some way to do this?
No. You must go up one level in the accessibility hierarchy. Implement the container protocol on your view's superview and return all of its descendants as children (and, thus, siblings of each other).
try this,
textfield.isAccessibilityElement = YES;
textfield.accessibilityElementsHidden = NO;
Leave the container methods for time being.
I’m implementing accessibility in a custom UITableViewCell class. I have a fairly simple overflow menu with a couple of buttons inside it, which are hidden until an ellipsis button is pushed that slides open and closes the overflow.
In my cell's initialiser I’m setting the accessibilityElementsHidden of my overflowContainer to YES. This seems to work, when scrolling through using VoiceOver, those views are skipped.
Then, when opening the cell, in the completion handler of the UIView animation, I set that same accessibilityElementsHidden of the same overflowContainer to NO. This doesn’t seem to have any effect, those elements are still skipped.
I’ve also tried posting UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil) before / after / when changing the accessibilityElementsHidden BOOL, but this also appears to have no effect on the situation.
Basically I’d like to toggle accessibilityElementsHidden on a couple of UIView instances at a specific point. Could anyone let me know what I may be doing wrong?
Here’s the code I fire when the overflow opens:
- (void)cellOverflowDidShow:(MyCell *)cell
{
self.overflowContainer.isAccessibilityElement = YES;
self.firstButton.isAccessibilityElement = YES;
self.secondButton.isAccessibilityElement = YES;
self.thirdButton.isAccessibilityElement = YES;
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, self.firstButton);
}
I fire the opposite when closing the cell (set all to NO and post notification again). And when initializing the cell, all I set is:
self.overflowContainer.isAccessibilityElement = NO;
Absolutely no idea why it shouldn’t be working, it appears I’m doing everything 100% correctly. If I don’t set the line in the initializer, the buttons all appear accessible (all the time). So it appears that the first call, be it YES or NO, works, but any subsequent ones are ignored.
In the visible state, you declare the overflow container to be an accessibility element. Thus, VoiceOver will allow the user to focus it rather than navigate child elements. Instead of toggling whether it's an accessibility element, keep self.overflowContainer.isAccessibilityElement set to NO and toggle the accessibility of its children, firstButton, secondButton, and thirdButton.
A shorthand for setting the accessibility of child elements is accessibilityElementsHidden. Try setting self.overflowContainer.accessibilityElementsHidden to NO when the view appears and YES when it disappears.
You may still need to trigger a layout change notification, regardless.
I just have a knowledge question about UIButtons / iOS in general.
Let's say you have a UIButton. You set the 'hidden' property to YES. This makes it no longer visible in view, right? But I noticed that while it's no longer visible, it is also no longer clickable either. So, does this mean that setting hidden = YES also sets enabled = NO?
Just curious. Thanks y'all.
UIButton and all controls inherits common properties from UIView like hidden, backgroundColor, etc.
Class reference of UIView says if any view is hidden then it will not receive input events
Class reference of UIView says:
A hidden view disappears from its window and does not receive input
events. It remains in its superview’s list of subviews, however, and
participates in autoresizing as usual. Hiding a view with subviews has
the effect of hiding those subviews and any view descendants they
might have. This effect is implicit and does not alter the hidden
state of the receiver’s descendants.
you can find this over Here.
It does. Setting the buttons hidden property to YES will disable any user interaction. This is true for other UI elements as well as just UIButton.
Yes you can't touch button when it is hidden.If you wanna touch it then you must make it btn.hidden = NO;. Hidden means disable the user interaction.
Not sure. Best way to find out would be an NSLog returning button.hidden
When us this line of code to logElementTree() in Instruments UIAutomation target.frontMostApp().mainWindow().logElementTree();
The results return is UIAElementNil
Even when I record a script and tap on the screen the only line that gets recorded is target.frontMostApp().tap();
you might have enabled accessibility for the main view.
if your provide the accessibility label for the main view then you will not get accessibility label for the child. try removing accessibility for the main view, you will get full hierarchy.
Don't set isAccessibilityElement = YES. If you do then the subviews of that element are hidden.
You should set accessibilityItentifier = #"xxxx"; isAccessibilityElement = NO;
Dont use "target.frontMostApp().mainWindow().logElementTree();", instead use "target.logElementTree()" always. It will display all the elements present on the current screen.
don't use target.frontMostApp().mainWindow().logElementTree();
Instead of your code replace it with this:
var target = UIATarget.localTarget();
target.logElementTree();