Android Accessibility
Bangalore Accessibility Week October 6-10, 2014 Ted Drake, Intuit Accessibility
- This presentation borrows heavily from the great presentations given by the Google Accessibility team at Google iO 2014
- Android Accessibility Videos
- Illustration by unknown: http://www.pinterest.com/pin/559501953680642594/
Accessibility Interaction
Users move accessibility focus by interacting with the touch screen using explore by touch and accessibility gestures.
AccessibilityServices interpret exploration and gestures to facilitate different types of navigation
AccessibilityService Documentation: An accessibility service runs in the background and receives callbacks by the system when AccessibilityEvents are fired. Such events denote some state transition in the user interface, for example, the focus has changed, a button has been clicked, etc. Such a service can optionally request the capability for querying the content of the active window. Development of an accessibility service requires extending this class and implementing its abstract methods.
Meet Talk Back
TalkBack is preinstalled on most Android devices, but is also available on the Play Store. TalkBack is enabled from Settings > Accessibility > TalkBack. Enabling TalkBack changes the interaction model of the device.
- Explore with a single finger.
- Double-tap to activate the focused item.
- Use two-finger drag to scroll lists.
- TalkBack support
Turn on TalkBack
This video shows how to enable TalkBack and how to use it as a developer.
Common Problems
Content Labeling
- All interactive elements must have a content description:
- android:contentDescription
- View#setContentDescription
- Decorative images:
- android:contentDescription=“@nullâ€
- For EditText
- android:hint
- labelFor
- Keep labels short and clear. Send Email
You spend a lot of time making your screens look great, but are you providing the same experience to TalkBack users? contentDescription allows you to own the experience. Setting the contentDescription to null will tell talkback to ignore the image. Use android:hint on form inputs, as the contentDescription will inherit the value of the input.
[code lang=”java”]
<textview android:layout_height="match_parent" android:labelfor="@+id/edit_item_name" android:text="Invoice amount">
<edittext android:id="@+id/edit_item_name" android:layout_height="wrap_content" android:hint="Invoice Amount">
[/code]
This example shows labelFor and android:hint being used on an input. The hint is not announced when the edit text has a value. More information by SSB Bart: Android Accessibility Properties and TalkBack
Grouping and Ordering
TalkBack uses view hierarchy order and on-screen positioning to determine grouping and ordering.
- Use ViewGroup containers to associate related information. Set android:focusable=“trueâ€
- The order of items displayed may be controlled.
- Use android:contentDescription or View#setContentDescription
Font Sizing
- Android supports large font substitution for low-vision users.
- Always use scale-independent pixels(sp).
- Avoid density-independent pixels (dip or dp)
- This is also important for i18n
WebViews
- Supported in Android 3.1+
- Enable JavaScript within WebView
- Garbage In, Garbage Out! Make sure your HTML is accessible. http://developer.android.com/reference/android/webkit/WebView.html
- WebViews are not accessible by default, the user must activate this because it uses a JavaScript driven ChromeVox ! The setting for this is ‘Enhanced Web Accessibility‘ or on older devices:’Inject Web Scripts’.This has been solved in KitKat, enhanced web accessibility is included when TalkBack is enabled.
- Turning on Accessibility mode, including ‘Explore by Touch’ in 4.0+.
Custom Views
This pie chart could be considered a custom view. TalkBack needs to tell the user about positioning, color, text. It also need to describe interactions, such as gestures, taps, and states.
Virtual View Hierarchy
- Pie Chart
- Om Parkash 30%
- clickable
- checkable
- Dev Anand 45%
- clickable
- checkable
- Aamir Khan 25%
- clickable
- checkable
What are the components? What are their states?
What TalkBack Sees
- ViewDecor
- Action Bar
- Pie Chart
- LinearLayout
- Favorite Actor
- Pie Chart
- Om Parkash 30%
- Dev Anand 45%
- Aamir Khan 25%
Custom Views
- Delegate accessibility support
- Map logical items to virtual views
- Expose information about views
- Formalize interaction model
setAccessibilityDelegate
[code lang=”java”]
ViewCompat.setAccessibilityDelegate(this, mAccessibilityHelper);
}
@Override
public boolean dispatchHoverEvent(MotionEvent event) {
if (mAccessibilityHelper != null && mAccessibilityHelper.dispatchHoverEvent(event)) {
return true;
}
return super.dispatchHoverEvent(event);
} [/code]
We want to check for mAccessibilityHelper support
Map Logical to Virtual
Reuse your existing code. The pie chart already:
- Is drawn on the screen
- Includes touch events
- Uniquely identified
[code lang=”java”]
@Override
protected int getVirtualViewAt(float x, float y) {
Wedge wedge = getWedgeAt(x, y);
if (wedge != null)
return wedge.getId();
return ExploreByTouchHelper.INVALID_ID;
}
@Override
protected void getVisibleVirtualViews(List<Integer> virtualViewIds) {
for (Wedge wedge : mWedges) {
virtualViewIds.add(wedge.getId());
}
} [/code]
Expose Information
Reuse existing code
- Position
- Color
- Label
- Relative Size
- Click Handling
- Checked Status
[code lang=”java”]
@Override
protected void onPopulateEventForVirtualView( int virtualViewId, AccessibilityEvent event) {
Wedge wedge = getWedgeForId(virtualViewId);
event.setContentDescription(wedge.getLabel() + ": " + wedge.getPercent() + "%");
}
@Override
protected void onPopulateNodeForVirtualView(int virtualViewId, AccessibilityNodeInfoCompat node) {
Wedge wedge = getWedgeForId(virtualViewId);
node.setContentDescription(wedge.getLabel() + ": " + wedge.getPercent() + "%");
node.setBoundsInParent(wedge.getLabelBounds());
… [/code]
Formalize Interactions
[code lang=”java”]
node.setCheckable(true);
node.setChecked(wedge.isChecked());
node.addAction(AccessibilityNodeInfoCompat.ACTION_CLICK);
}
@Override
protected boolean onPerformActionForVirtualView(int virtualViewId, int action, Bundle arguments) {
if (action == AccessibilityNodeInfoCompat.ACTION_CLICK) {
return onWedgeClicked(getWedgeForId(virtualViewId));
} [/code]
Assign your pre-existing actions to the accessibility node
Android L
- Custom AccessibilityAction
- Live Regions
- Collections
- Window API
Documentation is sparse for these new features. For more information, see the presentation from Google IO 14 and the Developer preview for Android L: Accessibility and Testing
AccessibilityAction
- Swipes and other hard to discover actions
- Actions are activated from the Local Context Menu
- Provide hints for actions Documentation for this has not yet been released.
Create AccessibilityAction
[code lang=”java”]/**
* @param actionId The id for this action. This should either be one of
* the standard actions or a specific action for your app. In that case it
* is required to use a resource identifier.
*/
public AccessibilityAction(int id, CharSequence label)
new AccessibilityAction(R.id.dismiss, getString(R.string.dismiss));
new AccessibilityAction(ACTION_CLICK, getString(R.string.play_song));
// Constants for all the standard actions with default label:
AccessibilityAction.ACTION_CLICK [/code]
Handling a Custom Action
[code lang=”java”]
eventView.setAccessibilityDelegate(new AccessibilityDelegate {
@Override
public onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(host, info);
info.addAction(new AccessibilityAction(R.id.dismiss,
}
@Override getString(R.string.dismiss)));
public boolean performAccessibilityAction(View host, int action, Bundle args) {
if (action == R.id.dismiss) {} // Logic for action
}
}); [/code]
Live Regions
- Based on the Live Region experience in HTML + ARIA
- Content is announced when it changes or appears on screen
- Look for TYPE_WINDOW_CONTENT_CHANGED
- Documentation on Android live regions not available yet.
Collections
- Similar to a data table in HTML
- Supports int, float, and Percent
- Query info about table and elements
- AccessibilityNodeInfo.CollectionInfo documentation
Window API
- Introspect all interactive windows: autocomplete, drawers…
- AccessibilityFocus can move from one window to another
- Retrieve information about properties of windows on the screen that sighted users can interact with.
- Retrieve a list of objects representing windows information: android.accessibilityservice.AccessibilityServic e.getWindows():
- TYPE_WINDOWS_CHANGED: AccessibilityEvent to see events
Android Testing
- Use Android Lint
- Use TalkBack’s Read From Top to make sure everything is announced on the screen
- Use the On-Screen Overlay to see what is being spoken
- Touch exploration help
Great post. Is there an updated post?