I'm having an issue with moving the voiceover cursor to a specific element on viewDidAppear. I followed Apple's guidelines for focusing on a specific element, in this case a dismiss button, but the cursor ends up elsewhere
Here is my Code:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification,
self.dismissButton);
}
Any help, ideas, would definitely be appreciated! thank you so much.
If I remember correctly i was not able to reliably focus on elements on first of the view as VO will generally focus on the top of the view.
The code you are doing is correct, but at this point the system will trigger it's own event and override yours.
What you can try to do is post a notification with a delay. But that will result in focus jumping around a little bit when opening the view.
It's not much of an answer, but that is where I'm at at the moment. I'll update you if I figure out a way to do it.
This answer may be of help.
Basically you need to wrap your elements in a container view if they're not in one already and then override the methods specified.
By giving your desired element a tag that is lower than the other elements you can have the view sort the array to ensure that it will be the first element in the accessibilityElements array used by VoiceOver. Or you can adapt the sort method to sort another way.
FYI: As of iOS 11, both UIAccessibilityScreenChangedNotification and UIAccessibilityLayoutChangedNotification reliably focus Voice Over elements for me.
Related
I'm working on a simple UI on a tvOS app and I'm facing a strange problem.
When a UISegmentedControl get focused you can move your focus around and it automatically changes the selected segment. But what I'm looking for is a way to limit the segment selection only when the user taps the segment, not when he focused it.
Any idea?
Thanks in advance.
You need to have your own internal variable for the selected segment and only change its value when the select button is pressed (which you can get using a gesture recognizer). When the segment loses focus (detectable in didUpdateFocus function) you assign the value of your internal variable to the selected index of the segment control.
You need to subclass UISegmentedControl then override didUpdateFocusInContext. In the "Custom Class" field in IB use the name of your custom class.
You can subclass UISegmentedControl and disable the behavior by defining:
#objc func _selectFocusedSegment(){
print ("select focused segment")
}
Beware that this solution is a hack. As far as I know there is no good, clean way to accomplish what you want short of steering clear of UISegmentedControl.
Also know that when a UISegmentedControl 'changes focus' between segments, it does not actually change focus. So hooking into focus updates like Nostradamus is suggesting will not work. To the focus engine UISegmentedControl behaves like a single large focusable element, not like a group of focusable segments. You can see this for yourself by debug inspecting a UIFocusUpdateContext on focusing towards or away from a UISegmentedControl.
I stumbled onto _selectFocusedSegment by defining a UISegmentedControl subclass and debug logging the various NSObject.perform methods, among others. My intent was to reverse engineer how UISegmentedControl retains a sticky last focused item, which is quite difficult to do on Apple TV. I was not able to find out exactly how UISegmentedControl manages focus, but I was able to find the answer to your question along the way.
I have a table with cells that the user may swipe to mark them "completed". I am trying to make this accessible using VoiceOver by implementing the accessbilityScroll method.
This works fine, but I can't figure out what cell has focus when the user scrolls.
I only find information on how to change focus.
Hehe, Ok. I just figured it out.
There is a protocol for this. Its called UIAccessibilityFocus
Method: accessibilityElementDidBecomeFocused:
Well, I will leave this question here to any one else that is out there struggling with this.
Your program can also tell where VoiceOver’s “focus” (the object that it’s dealing with) is, and when “focus” enters or leaves any given object.
For Focus Information click here
– accessibilityElementDidBecomeFocused
– accessibilityElementDidLoseFocus
– accessibilityElementIsFocused
As of iOS9, you can use
UIAccessibilityFocusedElement(UIAccessibilityNotificationVoiceOverIdentifier)
https://developer.apple.com/documentation/uikit/1615119-uiaccessibilityfocusedelement
I want to get the keyboard size without using NSNotification. When I press the plus button, it can replace the keyboard with a custom UIView like this:
Then the plus button is pressed and the view loaded:
How can I achieve this?
I already made same rookie mistake like you want to do here. The problem is you will write a lot only to realize you do not want to avoid standard flow provided you by iOS team. For example you will definitely have a bad time dealing with issue like this one (there is additional bar which is part of standard keyboard for Chinese locale):
I solved this by using other people's work from DAKeyboardControl project. You do not need to attach observer (or if you use DAKeyboardControl - block) directly to your bar with buttons, but to your controller and check what user is trying to do and animate this bar accordingly. In the sources you can see how to get keyboard's animation duration and timing function. It may sound more complicated than it indeed is, just give it a try.
How can I set voice over focus on my element (such like UITextView) in iOS 6. Is it possible?
Very simple. Just do this:
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, textView);
Note that it may not work, depending on where and when you use it. If you're trying to set the focus to a particular element from viewDidLoad, the code probably won't work correctly. This is because VoiceOver makes its own attempt to set the VoiceOver focus on an element initially; if VoiceOver does this before it processes your attempt to set focus, your code will work. But if VoiceOver gets around to setting the initial focused element after it processes your attempt, your code will appear to fail.
A somewhat more reliable way to do this in viewDidLoad is to use performSelector:withObject:withDelay:, to ensure that your call is processed after VoiceOver's initial focus setting.
i am trying to implement accessibility option in my book reader app. I have a slider(similar to ibooks) which is used for navigating between pages. i have seen this question posted by another user and implemented the same code in my app. Right now my slider is responding when i'm tapping on it. The voiceover is also speaking the label i have given in the code. But, the problem is that, i am unable to change the slider value and navigate to another page.. I dont know if it is the problem with my code or is it that i do not know how to replicate the gesture to change the value of the slider... Any help in this regard will be appreciated.... Thanku
Does the slider work with VoiceOver turned off?
If so, try swiping vertically up or down (top to bottom of display) after selecting the slider element with VoiceOver enabled.
Is it a UISlider, or something of your own devising? UISlider needs an actual vertical swipe once selected, and moves a pretty significant amount as a result — not a good experience for going to the next page.
If it's your own custom control, be sure you set UIAccessibilityTraitAdjustable.