Seeking advice for "dual mode" for increment/decrement of control with UIAccessibilityTraitAdjustable - ios

I implemented a custom iOS control (looking similar to a ruler), where the user can easily scroll to select one of about 300 values.
My control also has the trait UIAccessibilityTraitAdjustable and implements the methods accessibilityIncrement() and accessibilityDecrement() of the protocol UIAccessibilityAction to update its value. So far everything works as intended.
The problem is that adjusting the value via VoiceOver can be tedious, since each swipe gesture increments/decrements the value only by one. Is there a good way to offer a second mode where the updates happen, e.g. in steps of ten?

UIAccessibilityTraitAdjustable uses a fixed, developer-defined increment size. You can adjust the slider with a larger step size in -accessibilityIncrement if you think users will find it tedious to adjust the control one unit at a time. VoiceOver users desiring finer control can use the pass-through gesture (double tap and hold) to interact with the control directly, sliding to adjust it in single-percent increments. This does, however, assume users have fine motor control.
If you feel strongly that UIAccessibility should support a "fine-grain" adjustment mode, file an enhancement request with supporting use cases.

Related

ios voiceover slider double tap and hold, but for custom view

I've created a custom view that acts like a UISlider - there is a "track", and a handle to "grab" to change the value. For particular reasons, I can't just make it a subclass of UISlider. I'm trying to make this slider as accessible as possible with VoiceOver. I have accessibilityIncrease and accessibilityDecrease on my custom view that handle single finger drag up and single finger drag down. This changes the value of the slider by 10% at a time.
However, I'd like to allow more fine grained control, just like a non-VoiceOver slider. By default , UISlider has double tap and hold, and you can drag up/down to "pan" the slider. I'd like to add exactly that to my custom view, but I can't find the correct incantation to handle the double tap and hold gesture.
Is there something I can do to mimic the double tap and hold gesture from UISlider on my custom view?
Thanks very much!!!
If you want to implement this kind of new gesture for VoiceOver users, just forget it.
The recommended gesture for this kind of UI control is definitely the implementation of adjustable value as you already did apparently.
I don't think it's a good idea to try and implement new VoiceOver gestures in an application because its users have their habits and they may be totally lost with your customed control if they cannot handle it unless you add an hint to explain but that's definitely not what I recommend anyway.
Otherwise, you could take a look at the pass through concept introduced in the What's New in Accessibility WWDC 2017 video that deals with the same idea but for a panning gesture...

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?

How does UIAutomation determine whether a UIAElement.isVisible()

I have a view with the following structure:
GrandView
-Parent View1
-Parent View2
--Child View1
--Child View2
The child views take up almost all of the bounds of Parent View2, but there is still some space around the edges. I can select Parent View2 in the simulator with the accessibility inspector if I click on the edges. I can also tap Parent View2 in UIAutomation if I use:
tapWithOptions({tapOffset:{x:0.15, y:0.95}});
However, my calls to isVisible() always return 0. I expect that if I can tap the element, or select it with the accessibility inspector, it should return 1.
How does UIAutomation determine whether a UIAElement is visible?
Every operation you perform against an element has a timeout. This isn't obvious from the Apple documentation, but if you look at: setTimeout , it tells us:
The timeout value establishes a grace period for object resolution. If an object representing a UI element becomes available within the grace period, an attempt is made to instantiate that object from information retained by the instrument.
setTimeout itself just changes the default value (as do push and pop). What you really want to do is perform your action on your view, and fail on the timeout if it never becomes available (the default timeout is 5 seconds). The WWDC 2010 session "Automating User Interface Testing with Instruments" does go into this a little, it's available on the ADC WWDC 2010 page, with both video and slides. In your case, you'd want to execute the tap() on your view. If, for some reason, that view isn't available to UIAutomation within 5 seconds, you should see an exception. Experiment with changing the timeout by doing:
var oldTimeout = target.timeout();
target.pushTimeout(10);
before your code, and
target.popTimeout(oldTimeout);
after.
If it's a UIView, it should be driven the the hidden property. If it's not a view, and it's a container, it should be driven by accessibilityElementsHidden .
In general though, you don't want to use this for UIAutomation. Instead, whatever you were going to do on the view - in this case, a tap() - go ahead and do it, and let the system throw an error if it times out. In general this is the model you want to follow in your scripts rather than testing whether something is available first. Sine UIAutomation is DOM scripting the UIAccessibility information, when things like animated view transitions happen things get out of sync. Sometimes the script executes faster than the UI animates, and sometimes the opposite! waitForInvalid may be a shortcut to a solution for you.
Alex Vollmer's tuneup.js library for UIAutomation makes writing tests much easier, and is easy to extend.
https://github.com/alexvollmer/tuneup_js

how do i make UIKeyInput make repeated deleteBackwards calls

Currently I am using UIKeyinput but it is only sending a single delteBackward event even when I hold down the delete key for a long time.
How can I make it send me multiple event calls when I hold delete down for a long time?
There is no easy way to have the system keyboard do auto-repeat. These leaves you with two options:
Fake it by using an overlay on the keyboard (see the comment by #pho0)
Implement a custom keyboard, install it as the inputView for your view or view controller and implement a custom protocol that supports auto-repeat.
Solution 1 works well if you only need the delete key to auto-repeat, but if you need all the keys to auto-repeat the overlay code becomes as complex as the custom keyboard option. (The overlay needs a rectangle for each key, so why not just replace the underlaying keyboard).
Solution 2 involves a certain amount of "up-front" work... One way you might do this is define a key cap class (like a physical key) and a keyboard layout class.
I have implemented both solutions in projects I have worked on, but I currently use solution 2 since I can create whatever keyboard I like. In the simple case the use need never know that it is not the system keyboard. For power users they can customize the keyboard as they see fit.
For what it is worth, I found it useful to have the keyboard class be dumb; it just communicates that a key has transitioned to being down or has transitioned to being up. An additional class above that decides what action should be taken.
In some ways, I know this is not the answer you were looking for, but I hope it helps,
IDZ
One thing I've seen people do is put a fake button on top of the keyboard button. When someone is holding down on it, have a timer remove the last letter every time it fires.
Hope this helps.

Blackberry pixel-specific animated focus scrolling

Suppose I have a VFM full of both focusable and non-focusable fields. Since most of them are spread out far apart, the movement from one focused field to another is jerky at best, even with NullFields in between. In other words, it just sets the current y position to the next focused field without smoothly scrolling the screen.
What I want to achieve is to be able to scroll at a fixed rate between fields, so it it doesn't just focus from one to another that instantaneously. After reading up on how to do this, it is a matter of overriding moveFocus and setting it via a TimerTask from an accessor method to set moveFocus, as per this link. However, I haven't seen a practical implementation of how to do this, complete with the routines that are called in the TimerTask's thread.
Is there any way to achieve this type of behavior?

Resources