Set voice over focus on UITextView - ios

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.

Related

make UIAccessibilityTrait adjustable ignore double-tap (like a button) swift

I have a custom control to increment and decrement values. Now that I've added support for voice over, I've stumbled upon a problem.
My customView has the accessibility trait .adjustable and I implemented the correct methods for increasing and decreasing the values.
However, the voice over user can also double tap on that view to activate it. The problem is, that this triggers a gesture which is irrelevant to voice over users.
Is there a way to prevent an adjustable accessibility view from being activated so that the element is only adjustable, not double-tappable like a button?
There are two important properties to know when a double-tap occurs:
accessibilityActivate.
accessibilityActivationPoint.
In your case, you could just return true by overriding accessibilityActivate and if it's not enough, provide as well a CGPoint coordinate that triggers nothing (depends of your custom control and its neighborhood).
Otherwise, use the accessibilityElementIsFocused instance method to know wether you can trigger actions as this complete example shows up.
I ended up using UIAccessibility.isVoiceOverRunning to stop any tasks which would be triggered by a doubletap on that specific element.

iOS Keyboard (inside UIRemoteKeyboardWindow) is Not Shown When UITextField Becomes First Responder in Touch ID Completion Block (iOS 10)

I've recently discovered a problem in my app that only seems to occur in iOS 10 where the system keyboard does not display when programmatically triggering a text field to become first responder inside of a completion handler -- specifically the completion handler I get back from a Touch ID attempt.
The crazy part of this issue is, even though the keyboard is not shown, the area on the iPhone where the keyboard normally would be is still responding to touch inputs as if the user is typing on the keyboard!
After doing a lot of investigation and debugging into the issue, I stumbled across the fact that the hidden property is set to YES on the private UIRemoteKeyboardWindow that gets created after becomeFirstResponder is invoked on the text field. In other situations where I bring up the keyboard, the value of that hidden property is set to NO.
Has anybody else run into this problem in iOS 10? If so, anybody found a solution to this? I tried manually setting the hidden value to YES on the window instance but that had no effect on it. I'm pretty much grasping at straws at this point.
Attachments:
Here's the output of the windows from the UIApplication instance when the text field becomes first responder outside of the Touch ID completion handler (pay close attention to UIRemoteKeyboardWindow):
And when the UITextField becomes the first responder inside the Touch ID handler...
First Update
So I did not consider the becomeFirstResponder being done on the main thread before that some have pointed out, but unfortunately, it did not resolve the issue -- however, I did make some additional discoveries. The hidden window issue seems to stem from outputting the details of the UIApplication instance's windows immediately after issuing the becomeFirstResponder action. After doing that, I set a breakpoint on the UITextField editing callback and proceed to interact with the keyboard (that is invisible) -- and when I output the window details, it doesn't seem like the hidden property is ever set to YES (which can possibly rule out that property being set as the cause of the issue), but I still have an invisible keyboard! I started debugging the view hierarchy and below is a screenshot of what it looks like when I examine the keyboard window:
Hopefully you guys can see what I discovered here which is that the keys are present but there appears to be some white view blocking them from sight. The thing is, I don't even see those white views on my app screen. I just see what normally sits behind the keyboard when it's present.
As a temporary workaround, call becomeFirstResponder after a delay fixed this, however, not happy with the hacky solution.
Looks like the issue occurring for different scenarios too - keyboard could be invisible even if you are selecting the textField manually after cancelling touchId alert.

iOS Accessibility - Change AccessibilityElementsHidden without delay?

I am working on a view in which certain elements will be removed and re-added as accessible items depending on the state of the view. I have been able to successfully achieve the functionality I desire by setting AccessibilityElementsHidden to toggle the state.
However, I am finding that there is a brief pause (~1-2 seconds) between this field being set before the Accessibility Layout is updated, which can allow the user to highlight a deactivated accessibility element if they are moving at a reasonable pace. If they are focused on an item as it is being disabled it makes it difficult to re-orient oneself in the VoiceOver interface.
I have found methods to immediately update the display of the interface (by means of SetNeedsLayout() and LayoutIfNeeded() on the main thread) but unfortunately this does not trigger the Accessibility Layout update.
I have also tried using UIAccessibilityPostNotification.LayoutChanged but like the changing of the AccessibilityElementsHidden property, this also takes a moment to propagate to the view.
Can anyone provide some insight as to what I need to do to ensure the user cannot put themselves in a bad state before the Accessible Layout is applied?

Prevent UISegmentedControl segment selection on focus on tvOS

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.

UIAccessibilityFocus protocol not working with UITextField

With UIAccessibilityFocus protocol, supposedly, if you override accessibilityElementDidBecomeFocused() and accessibilityElementDidLoseFocus(), you will be able to track when an accessible element gain or lose focus while Voiceover is running. This seems to work well with all field types - UIButton, UILabel, UISwitch, UITextView, etc. - except UITextField. When Voiceover focus is on (or leaving) an UITextField, those functions are simply not called. Just wondering if it is a bug or something else. Thanks!
This is a feature, let me explain.
Without VoiceOver turned on there is no concept of focus within iOS. Except in the case of UITextField. UITextFields get "focused" (again focus isn't really a concept in iOS without voiceover) with or without VoiceOver on. For the other elements, this is not the case. They do not have "gainFocus" equivalents. A UIButton gaining focus is only meaningful from an accessibility standpoint. So they add in the special accessibilityElementDidGainFocus calls for those classes. They are specifically removed from UITextFields because that call would be logically equivalent to calls that already exist for that class, independent of the Accessibility API.

Resources