While Google has done a great job improving Android’s Accessibility API, it’s still not nearly as robust as Apple’s iOS Accessibility API. See a comparison of Web Accessibility and WAI-ARIA support in Android and iOS. Learn what ARIA features work in one, both, or neither of these mobile platforms. Learn what’s possible with accessibility development for Native Android & iOS Apps. It's iOS 7 vs. Android 4.4 KitKat in their never ending race towards ultimate accessibility champion!
http://pauljadam.com/iosvsandroida11y
Accessibility Evangelist at Deque Systems, Inc.
Press the Left/Right Arrow Keys or Page Up/Down to navigate through slides, the Home key takes you home to the table of contents.
This slideshow has been developed with jQuery Mobile to create a universally accessible presentation that will work on any accessibility enabled device. PowerPoint & PDF formats are not universally accessible.
Apple does a great job marketing their accessibility features and including helpful screenshots. At their links below screenshots show VoiceOver speech bubbles explaining how their screen reader works, showing how to use two fingers to turn the VoiceOver Rotor, and other accessibility features for Hearing, Physical, and Learning disabilities.
The iOS 7 User Guide is available in HTML and explains all the VoiceOver settings including how to control the screen reader with different finger combinations, swipes, and taps. It also explains how to use quick navigation gestures and key commands to quickly navigate web pages and test for accessibility using the Rotor or a Keyboard.
iOS 7 User Guide in HTML (Go to Accessibility > VoiceOver)
Below are some screencast videos that show how to use the VoiceOver Practice feature where you can test the different finger combinations and gestures to see what they do without actually activating the command. They also show how to use the Rotor and do basic HTML accessibility testing.
The best first step to learn TalkBack is to launch the “Explore by touch” tutorial from TalkBack > Settings for an interactive tutorial where it teaches you how to use TalkBack on your phone or tablet.
More advanced features of TalkBack that you should learn to use include: how to temporarily pause speech, display spoken output on the screen, and learn the shortcut gestures including the global and local context menus.
…supporting accessibility does not impact your ability to innovate and create beautiful iPhone applications.
…thin layer of functionality that does not alter your application’s appearance, or interfere with its main logic.
/*
Return YES if the receiver should be exposed as an accessibility element.
default == NO
default on UIKit controls == YES
Setting the property to YES will cause the receiver to be visible to assistive applications.
*/
@property(nonatomic) BOOL isAccessibilityElement;
/*
Returns the localized label that represents the element.
If the element does not display text (an icon for example), this method
should return text that best labels the element. For example: "Play" could be used for
a button that is used to play music. "Play button" should not be used, since there is a trait
that identifies the control is a button.
default == nil
default on UIKit controls == derived from the title
Setting the property will change the label that is returned to the accessibility client.
*/
@property(nonatomic, copy) NSString *accessibilityLabel;
/*
Returns a localized string that describes the result of performing an action on the element, when the result is non-obvious.
The hint should be a brief phrase.
For example: "Purchases the item." or "Downloads the attachment."
default == nil
Setting the property will change the hint that is returned to the accessibility client.
*/
@property(nonatomic, copy) NSString *accessibilityHint;
/*
Returns a localized string that represents the value of the element, such as the value
of a slider or the text in a text field. Use only when the label of the element
differs from a value. For example: A volume slider has a label of "Volume", but a value of "60%".
default == nil
default on UIKit controls == values for appropriate controls
Setting the property will change the value that is returned to the accessibility client.
*/
@property(nonatomic, copy) NSString *accessibilityValue;
/*
Returns a UIAccessibilityTraits mask that is the OR combination of
all accessibility traits that best characterize the element.
See UIAccessibilityConstants.h for a list of traits.
When overriding this method, remember to combine your custom traits
with [super accessibilityTraits].
default == UIAccessibilityTraitNone
default on UIKit controls == traits that best characterize individual controls.
Setting the property will change the traits that are returned to the accessibility client.
*/
@property(nonatomic) UIAccessibilityTraits accessibilityTraits;
Accessibility traits that tell an assistive application how an accessibility element behaves or should be treated.
UIAccessibilityTraits UIAccessibilityTraitNone;
UIAccessibilityTraits UIAccessibilityTraitButton;
UIAccessibilityTraits UIAccessibilityTraitLink;
UIAccessibilityTraits UIAccessibilityTraitSearchField;
UIAccessibilityTraits UIAccessibilityTraitImage;
UIAccessibilityTraits UIAccessibilityTraitSelected;
UIAccessibilityTraits UIAccessibilityTraitPlaysSound;
UIAccessibilityTraits UIAccessibilityTraitKeyboardKey;
UIAccessibilityTraits UIAccessibilityTraitStaticText;
UIAccessibilityTraits UIAccessibilityTraitSummaryElement;
UIAccessibilityTraits UIAccessibilityTraitNotEnabled;
UIAccessibilityTraits UIAccessibilityTraitUpdatesFrequently;
UIAccessibilityTraits UIAccessibilityTraitStartsMediaSession;
UIAccessibilityTraits UIAccessibilityTraitAdjustable;
UIAccessibilityTraits UIAccessibilityTraitAllowsDirectInteraction;
UIAccessibilityTraits UIAccessibilityTraitCausesPageTurn;
UIAccessibilityTraits UIAccessibilityTraitHeader; (Adds element to the Headings Rotor Quick Navigation)
/*
UIAccessibilityPostNotification
This function posts a notification to assistive applications.
Some notifications specify a required or optional argument.
Pass nil for the argument if the notification does not specify otherwise.
See UIAccessibilityConstants.h for a list of notifications.
*/
UIKIT_EXTERN void UIAccessibilityPostNotification(UIAccessibilityNotifications notification, id argument);
@property (nonatomic, copy) UIBezierPath *accessibilityPath NS_AVAILABLE_IOS(7_0);
/*
Informs whether the receiving view should be considered modal by accessibility. If YES, then
elements outside this view will be ignored. Only elements inside this view will be exposed.
default == NO
*/
@property(nonatomic) BOOL accessibilityViewIsModal NS_AVAILABLE_IOS(5_0);
@property(nonatomic) BOOL shouldGroupAccessibilityChildren NS_AVAILABLE_IOS(6_0);
/*
Implement accessibilityActivate on an element in order to handle the default action.
For example, if a native control requires a swipe gesture, you may implement this method so that a
VoiceOver user will perform a double-tap to activate the item.
If your implementation successfully handles activate, return YES, otherwise return NO.
default == NO
*/
- (BOOL)accessibilityActivate NS_AVAILABLE_IOS(7_0);
/*
Return an array of UIAccessibilityCustomAction objects to make custom actions for an element accessible to an assistive technology.
For example, a photo app might have a view that deletes its corresponding photo in response to a flick gesture.
If the view returns a delete action from this property, VoiceOver and Switch Control users will be able to delete photos without performing the flick gesture.
default == nil
*/
@property (nonatomic, retain) NSArray *accessibilityCustomActions NS_AVAILABLE_IOS(8_0);
/*
Implement accessibilityPerformEscape on an element or containing view to exit a modal or hierarchical interface view.
For example, UIPopoverController implements accessibilityPerformEscape on it's root view, so that when
called (as a result of a VoiceOver user action), it dismisses the popover.
If your implementation successfully dismisses the current UI, return YES, otherwise return NO.
default == NO
*/
- (BOOL)accessibilityPerformEscape NS_AVAILABLE_IOS(5_0);
/*
Implement accessibilityPerformMagicTap on an element, or the application, in order to provide a context-sensitive action.
For example, a music player can implement this to start and stop playback, or a recording app could start and stop recording.
Return YES to indicate that the action was handled.
default == NO
*/
- (BOOL)accessibilityPerformMagicTap NS_AVAILABLE_IOS(6_0);
/*
Assistive Technology
Use UIAccessibilityIsVoiceOverRunning() to determine if VoiceOver is running.
Listen for UIAccessibilityVoiceOverStatusChanged to know when VoiceOver starts or stops.
*/
UIKIT_EXTERN BOOL UIAccessibilityIsVoiceOverRunning() NS_AVAILABLE_IOS(4_0);
UIKIT_EXTERN NSString *const UIAccessibilityVoiceOverStatusChanged NS_AVAILABLE_IOS(4_0);
// Returns whether system audio is mixed down from stereo to mono.
UIKIT_EXTERN BOOL UIAccessibilityIsMonoAudioEnabled() NS_AVAILABLE_IOS(5_0);
UIKIT_EXTERN NSString *const UIAccessibilityMonoAudioStatusDidChangeNotification NS_AVAILABLE_IOS(5_0);
// Returns whether the system preference for closed captioning is enabled.
UIKIT_EXTERN BOOL UIAccessibilityIsClosedCaptioningEnabled() NS_AVAILABLE_IOS(5_0);
UIKIT_EXTERN NSString *const UIAccessibilityClosedCaptioningStatusDidChangeNotification NS_AVAILABLE_IOS(5_0);
// Returns whether the system preference for invert colors is enabled.
UIKIT_EXTERN BOOL UIAccessibilityIsInvertColorsEnabled() NS_AVAILABLE_IOS(6_0);
UIKIT_EXTERN NSString *const UIAccessibilityInvertColorsStatusDidChangeNotification NS_AVAILABLE_IOS(6_0);
// Returns whether the app is running under Guided Access mode.
UIKIT_EXTERN BOOL UIAccessibilityIsGuidedAccessEnabled() NS_AVAILABLE_IOS(6_0);
UIKIT_EXTERN NSString *const UIAccessibilityGuidedAccessStatusDidChangeNotification NS_AVAILABLE_IOS(6_0);
// Returns whether the system preference for bold text is enabled
UIKIT_EXTERN BOOL UIAccessibilityIsBoldTextEnabled() NS_AVAILABLE_IOS(8_0);
UIKIT_EXTERN NSString *const UIAccessibilityBoldTextStatusDidChangeNotification NS_AVAILABLE_IOS(8_0);
// Returns whether the system preference for grayscale is enabled
UIKIT_EXTERN BOOL UIAccessibilityIsGrayscaleEnabled() NS_AVAILABLE_IOS(8_0);
UIKIT_EXTERN NSString *const UIAccessibilityGrayscaleStatusDidChangeNotification NS_AVAILABLE_IOS(8_0);
// Returns whether the system preference for reduce transparency is enabled
UIKIT_EXTERN BOOL UIAccessibilityIsReduceTransparencyEnabled() NS_AVAILABLE_IOS(8_0);
UIKIT_EXTERN NSString *const UIAccessibilityReduceTransparencyStatusDidChangeNotification NS_AVAILABLE_IOS(8_0);
// Returns whether the system preference for reduce motion is enabled
UIKIT_EXTERN BOOL UIAccessibilityIsReduceMotionEnabled() NS_AVAILABLE_IOS(8_0);
UIKIT_EXTERN NSString *const UIAccessibilityReduceMotionStatusDidChangeNotification NS_AVAILABLE_IOS(8_0);
// Returns whether the system preference for darker colors is enabled
UIKIT_EXTERN BOOL UIAccessibilityDarkerSystemColorsEnabled() NS_AVAILABLE_IOS(8_0);
UIKIT_EXTERN NSString *const UIAccessibilityDarkerSystemColorsStatusDidChangeNotification NS_AVAILABLE_IOS(8_0);
Develop - API Guides - Accessibility - Making Applications Accessible
Note: For EditText fields, provide an android:hint attribute instead of a content description, to help users understand what content is expected when the text field is empty. When the field is filled, TalkBack reads the entered content to the user, instead of the hint text.
contentDescription on an EditText control is only read before text is typed into the field, once the field is emptied the contentDescription is no longer read. This is a reason why a hint is a better option. Even though both disappear as the accessible name once text is typed into the field the hint comes back into view when the field is emptied and it will be read again by TalkBack, not the case for contentDescription on EditText controls.
Labels that won't change while using the app (such as "Next" or "Purchase") can be added via the XML layout by setting a UI element's android:contentDescription attribute:
<Button
android:id=”@+id/next_button”
android:src=”@drawable/next”
android:contentDescription=”@string/next”/>
Base the content description on some context, such as the state of a toggle button, or a piece of selectable data like a list item. To edit the content description at runtime, use the setContentDescription() method:
String contentDescription = "Select " + strValues[position];
label.setContentDescription(contentDescription);
Avoid the web-developer pitfall of labelling everything with useless information. For instance, don't set an application icon's content description to "app icon". That just increases the noise a user needs to navigate in order to pull useful information from your interface.
<TextView android:id="@+id/tv_caption" android:labelFor="@+id/edit_rate" android:text="@string/txt_rate"> </TextView >
<EditText android:id="@+id/edit_rate"> </EditText>
setFocusable()
isFocusable()
requestFocus()
If a view is not focusable by default, you can make it focusable in your layout file by setting the android:focusable attribute to true or by calling the its setFocusable() method.
Each UI control has 4 attributes, android:nextFocusUp, android:nextFocusDown, android:nextFocusLeft, and android:nextFocusRight, which you can use to designate the next view to receive focus when the user navigates in that direction.
Note: You can modify the focus order of user interface components at runtime, using methods such as setNextFocusDownId() and setNextFocusRightId().
android:importantForAccessibility
android:importantForAccessibility=“no"
noHideDescendants - The view is NOT important for accessibility, nor are any of its descendant views.
setImportantForAccessibility(int)
Stop images from being focusable with TalkBack by setting android:focusable=“false” or android:importantForAccessibility=“no”(which overrides :focusable on an ImageView)
View.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED)
Android Accessibility Testing and Fixing in 30 seconds
Deque recently introduced a WorldSpace Xcode plugin to do automated accessibility testing for iOS!
view.announceForAccessibility("Hello TalkBack World");
There are no traits, no hints on all elements, etc. If you want a UI element to be spoken as a "button" to TalkBack then you must use a button or image button element since there is no button trait(role).
No accessibilityViewIsModal like iOS, the API is just not nearly as robust!
EditText elements can't have both a contentDescription and a hint! And as soon as you type some text the hint or contentDescription is NOT spoken.
Android handles links embedded in a textview by using an earcon ding but no role/trait to indicate the separate elements. They're not separately focusable!
Opening local context menu gives ability to activate separate links but this is not very obvious or documented much.
TalkBack users do not hear if something is actionable unless it's a button or input element.
Tab controls do not indicate a tab role or a selected state.
Not all old school HTML accessibility methods like Fieldset & Legend or the <td> headers attribute work on all mobile devices like iOS.
Quick Navigation by Semantic HTML Elements with Screen Readers
Semantic HTML Mobile Accessibility Support
Android users can download multiple browsers with different rendering engines like Chrome and Firefox. The different Android browsers have different levels of accessibility and stability bugs. Firefox is actually the most accessible browser for Android. Accessibility testing differs with TalkBack on Chrome vs. Firefox.
While iOS users can download different browsers like Chrome, these 3rd-party browsers are actually running Apple's Webkit rendering engine underneath the covers so there is no differences in accessibility of HTML on Mobile Safari vs Chrome for iOS.
WCAG requires the language of the document bet set, e.g. lang="en". Setting the document language to a value supported by the screen reader will cause the synthesizer to automatically switch to the correct language and speak an accurate pronunciation of the words in the correct dialect.
In this Live Demo, with VoiceOver set to the default language in the Rotor, reading this German news story VO will automatically switch from US English to German: Ex-Verfassungsrichter: Staat muss vor NSA-Ausspähung schützen
Languages with JAWS and MAGic on the Internet
The TalkBack screen reader for Android (Chrome or Firefox) does not support Language Detection, switching synthesizer based on lang attribute.
The CSS Speech Module W3C specification offers interesting properties that work only with VoiceOver for iOS to control how VoiceOver speaks text strings.
For example, in the below code snippet with {speak: literal-punctuation;} we can tell the VoiceOver screen reader (for iOS only) to speak all special characters including the asterisks, brackets, colons, semicolons, at symbols, and quotation marks. If this CSS property is not used then by default only the * and @ are read out loud by VoiceOver.
UIImageView *view = [[UIImageView alloc] initWithImage:image]; view.accessibilityLabel = @"Apple Logo";
<style>
.address, .phone, .zip {speak: digits;}
code {speak: literal-punctuation;}
</style>
Mobile Safari is your ONLY option on iOS. Any browsers like Chrome for iOS run as a skin on top of Apple's accessible browser.
Chrome is super buggy which is sad as it's the default browser app installed on Android. Chrome does this weird thing where as soon as I swipe to a text input the accessible name is NOT spoken and instead the keyboard appears automatically and TalkBack quickly interrupts yo to say "Showing text keyboard web view"
New features for TalkBack users in Firefox for Android 24
What’s New for TalkBack users in Firefox 25 for Android
First round of accessibility support for Android in mobile Firefox | Marco’s accessibility blog
Quick Navigation keys now in nightly builds of Firefox native for Android | Marco’s accessibility blog
Key | Description |
---|---|
a | Moves to next named anchor |
b | Moves to next button |
c | Moves to next combobox or listbox |
e | Moves to next text entry or password field |
f | Moves to next form field (button, combobox, text entry, radio button, slider, checkbox) |
g | Moves to next graphic |
h | Moves to next heading of any level |
i | Moves to next item in an unordered, ordered or definition list |
k | Moves to next hyperlink |
l | Moves to next unordered, ordered or definition list |
p | Moves to next page tab (in ARIA-enabled web apps) |
r | Moves to next radio button |
s | Moves to next separator |
t | Moves to next data table |
x | Moves to next checkbox |
How to use TalkBack support in Firefox for Android for accessibility
iOS and Android have excellent support for WAI-ARIA, even better than some desktop browsers and screen readers.
Placeholder always fails contrast by default :(
::-webkit-input-placeholder { color: #666; }
:-moz-placeholder { /* Firefox 18- */ color: #666; }
::-moz-placeholder { /* Firefox 19+ */ color: #666; }
:-ms-input-placeholder { color: #666; }
map view not accessible on android the + - buttons and map pins have no accessible names
map pin detail tooltips not accessible at all
Only the list view is accessible
The Map view pins are accessible and indicate their selected state. This is likely a limitation of google's map view API.
Best Android Keyboards for Limited Dexterity (or anyone)
Best Alternative Android Keyboards for the rest of us with fat fingers, poor dexterity, arthritis, repetitive stress injuries, paralysis, and other finger/hand limitations.