354 lines
17 KiB
Plaintext
354 lines
17 KiB
Plaintext
page.title=Designing for Accessibility
|
||
@jd:body
|
||
|
||
|
||
<div id="qv-wrapper">
|
||
<div id="qv">
|
||
|
||
<h2>Quickview</h2>
|
||
<ul>
|
||
<li>To make your application more accessible, you should make sure your UI is navigable
|
||
using a directional controller and your widgets provide content descriptions</li>
|
||
<li>If you implement a custom view, you should ensure that it delivers the appropriate
|
||
accessibility events during user interaction</li>
|
||
</ul>
|
||
|
||
<h2>In this document</h2>
|
||
<ol>
|
||
<li><a href="#Navigation">Allow Navigation with a Directional Controller</a>
|
||
<ol>
|
||
<li><a href="#FocusOrder">Controlling focus order</a></li>
|
||
<li><a href="#ClickingDpad">Clicking with a directional controller</a></li>
|
||
</ol>
|
||
</li>
|
||
<li><a href="#LabelInputs">Label Your Input Widgets</a></li>
|
||
<li><a href="#UiBestPractices">Follow Android UI Best Practices</a></li>
|
||
<li><a href="#CustomViews">Send Accessibility Events from Custom View Components</a></li>
|
||
<li><a href="#Test">Test Your Application’s Accessibility</a></li>
|
||
</ol>
|
||
|
||
<h2>Key classes</h2>
|
||
<ol>
|
||
<li>{@link android.view.accessibility.AccessibilityEvent}</li>
|
||
<li>{@link android.view.accessibility.AccessibilityEventSource}</li>
|
||
</ol>
|
||
|
||
<h2>Related samples</h2>
|
||
<ol>
|
||
<li><a
|
||
href="{@docRoot}resources/samples/AccessibilityService/index.html">Accessibility Service</a></li>
|
||
</ol>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
|
||
|
||
<p>Many Android users have disabilities that require them to interact with their Android devices in
|
||
different ways. These include users who have visual, physical or age-related disabilities that
|
||
prevent them from fully using or seeing a touchscreen.</p>
|
||
|
||
<p>Android provides an accessibility layer that helps these users navigate their Android-powered
|
||
devices more easily. Android's accessibility services provide things like text-to-speech, haptic
|
||
feedback, and trackball/d-pad navigation that augment the user experience.</p>
|
||
|
||
<p>Your application should follow the guidelines in this document to ensure that it provides a
|
||
good experience for users with disabilities. Following these two basic rules will solve most
|
||
access-related problems:</p>
|
||
|
||
<ul>
|
||
<li>Make all of your user interface controls accessible with a trackball or directional
|
||
controller (d-pad).</li>
|
||
<li>Label your {@link android.widget.ImageButton}, {@link android.widget.EditText}, and other input
|
||
widgets using the <a
|
||
href="{@docRoot}reference/android/view/View.html#attr_android:contentDescription">{@code
|
||
android:contentDescription}</a> attribute.</li>
|
||
</ul>
|
||
|
||
|
||
|
||
<h2 id="Navigation">Allow Navigation with a Directional Controller</h2>
|
||
|
||
<p>Many Android devices come with some sort of directional controller, such as:</p>
|
||
<ul>
|
||
<li>A clickable trackball that users can move in any direction</li>
|
||
<li>A clickable d-pad that allows users to navigate in four directions.</li>
|
||
<li>Arrow keys and an OK button that’s equivalent to clicking a trackball or d-pad.</li>
|
||
</ul>
|
||
|
||
<p>All of these directional controllers allow users to navigate the screen without using the
|
||
touchscreen. On some devices, a user can also navigate to the top or bottom of a list by holding
|
||
down the <em>alt</em> key while pressing a discrete key for up or down.</p>
|
||
|
||
<p>A directional controller is the primary means of navigation for users with visual or some
|
||
physical impairments (and also for users without impairments when using devices that don't
|
||
have a touchscreen). You should verify that all UI controls in your application are
|
||
accessible without using the touchscreen and that clicking with the center button (or OK button) has
|
||
the same effect as touching the controls on the touchscreen.</p>
|
||
|
||
<p>A UI control (also called a "widget") is accessible using directional controls when it's
|
||
"focusable" property is "true." This means that users can focus on the widget using the directional
|
||
controls and then interact with it. Widgets provided by the Android APIs are focusable by default
|
||
and visually indicate focus by changing the widget visual appearance in some way.</p>
|
||
|
||
<p>Android provides several APIs that let you control whether a widget is focusable and even
|
||
request that a widget be given focus. Such methods include:</p>
|
||
|
||
<ul>
|
||
<li>{@link android.view.View#setFocusable setFocusable()}</li>
|
||
<li>{@link android.view.View#isFocusable isFocusable()}</li>
|
||
<li>{@link android.view.View#requestFocus requestFocus()}</li>
|
||
</ul>
|
||
|
||
<p>When working with a view that is not focusable by default, you can make it focusable from the XML
|
||
layout file by setting the <a
|
||
href="{@docRoot}reference/android/view/View.html#attr_android:focusable">{@code
|
||
android:focusable}</a> attribute to {@code "true"}.</p>
|
||
|
||
|
||
|
||
<h3 id="FocusOrder">Controlling focus order</h3>
|
||
|
||
<p>When the user navigates in any direction using the directional controls, focus is passed from one
|
||
view to another, as determined by the focus ordering. The ordering of the focus movement is based on
|
||
an algorithm that finds the nearest neighbor in a given direction. In rare cases, the default
|
||
algorithm may not match the order that you intended for your UI. In these situations, you can
|
||
provide explicit overrides to the ordering using the following XML attributes in the layout
|
||
file:</p>
|
||
|
||
<dl>
|
||
<dt><a href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusDown"
|
||
>{@code android:nextFocusDown}</a></dt>
|
||
<dd>Defines the next view to receive focus when the user navigates down.</dd>
|
||
<a><a href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusLeft"
|
||
>{@code android:nextFocusLeft}</a></dt>
|
||
<dd>Defines the next view to receive focus when the user navigates left.</dd>
|
||
<dt><a href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusRight"
|
||
>{@code android:nextFocusRight}</a></dt>
|
||
<dd>Defines the next view to receive focus when the user navigates right.</dd>
|
||
<dt><a href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusUp"
|
||
>{@code android:nextFocusUp}</a></dt>
|
||
<dd>Defines the next view to receive focus when the user navigates up.</dd>
|
||
</dl>
|
||
|
||
<p>For example, here is an XML layout that contains a focusable {@link android.widget.TextView}.
|
||
While the {@link android.widget.TextView} is located to the right of the {@link
|
||
android.widget.EditText}, it can now be reached by pressing the down arrow when focus is on the
|
||
{@link android.widget.EditText}: </p>
|
||
|
||
<pre>
|
||
<LinearLayout android:orientation="horizontal"
|
||
... >
|
||
<EditText android:id="@+id/edit"
|
||
android:nextFocusDown=”@+id/text”
|
||
... />
|
||
<TextView android:id="@+id/text"
|
||
android:focusable=”true”
|
||
android:text="Hello, I am a focusable TextView"
|
||
android:nextFocusUp=”@id/edit”
|
||
... />
|
||
</LinearLayout>
|
||
</pre>
|
||
|
||
<p>When modifying this ordering, be sure that the navigation works as expected in all directions
|
||
from each widget and when navigating in reverse (to get back to where you came from).</p>
|
||
|
||
<p>You can also modify the focus ordering at runtime, using methods in the {@link
|
||
android.view.View} class, such as {@link android.view.View#setNextFocusDownId
|
||
setNextFocusDownId()} and {@link android.view.View#setNextFocusRightId
|
||
setNextFocusRightId()}.</p>
|
||
|
||
|
||
<h3 id="ClickingDpad">Clicking with a directional controller</h3>
|
||
|
||
<p>On most devices, clicking a view using a directional controller sends a {@link
|
||
android.view.KeyEvent} with {@link android.view.KeyEvent#KEYCODE_DPAD_CENTER} to the view currently
|
||
in focus. Make sure this event has the same effect as touching the view on the touchscreen. All
|
||
standard Android views already handle {@link android.view.KeyEvent#KEYCODE_DPAD_CENTER}
|
||
appropriately.</p>
|
||
|
||
<p>If possible, also treat the {@link android.view.KeyEvent#KEYCODE_ENTER} event the same as
|
||
{@link android.view.KeyEvent#KEYCODE_DPAD_CENTER}. That makes interaction much easier from a full
|
||
keyboard.</p>
|
||
|
||
|
||
|
||
|
||
<h2 id="LabelInputs">Label Your Input Widgets</h2>
|
||
|
||
<p>Many input widgets rely on visual cues to inform the user of their meaning. For example, a
|
||
notepad application might use an {@link android.widget.ImageButton} with a picture of a plus sign to
|
||
indicate that the user can add a new note. Or, an {@link android.widget.EditText} may have
|
||
a label near it that indicates its purpose. When a visually impaired user accesses your
|
||
application, these visual cues are often useless.</p>
|
||
|
||
<p>To provide textual information about these widgets (as an alternative to the visual cues), you
|
||
should use the <a href="{@docRoot}reference/android/view/View.html#attr_android:contentDescription"
|
||
>{@code android:contentDescription}</a> attribute. The text you provide in this attribute
|
||
is not visible on the screen, but if a user has enabled accessibility speech tools then the
|
||
description in this attribute is read aloud to the user.</p>
|
||
|
||
<p>You should set the <a
|
||
href="{@docRoot}reference/android/view/View.html#attr_android:contentDescription" >{@code
|
||
android:contentDescription}</a> attribute on every {@link android.widget.ImageButton}, {@link
|
||
android.widget.EditText}, {@link android.widget.CheckBox}, and on any other input widgets that might
|
||
benefit users with extra information.</p>
|
||
|
||
<p>For example, the following {@link android.widget.ImageButton} sets the content description for
|
||
the plus button to the {@code add_note} string resource, which might be defined in English as
|
||
“Add note":</p>
|
||
|
||
<pre>
|
||
<ImageButton
|
||
android:id=”@+id/add_entry_button”
|
||
android:src=”@drawable/plus”
|
||
android:contentDescription=”@string/add_note”/>
|
||
</pre>
|
||
|
||
<p>This way, when using speech accessibility tools, the user hears "Add note" when focused on
|
||
this widget.</p>
|
||
|
||
|
||
|
||
<h2 id="UiBestPractices">Follow Android UI Best Practices</h2>
|
||
|
||
<p>You can make it easier for users to learn how to use your application by developing a user
|
||
interface that complies with Android's standard interaction patterns, instead of creating your own
|
||
or using interaction patterns from another platform. This consistency is especially important for
|
||
many disabled users, as they may have less contextual information available to try to understand
|
||
your application’s interface.</p>
|
||
|
||
<p>Specifically, you should:</p>
|
||
|
||
<ul>
|
||
<li>Use the platform's built-in widgets and layouts whenever possible, as these views provide
|
||
accessibility support by default.</li>
|
||
<li>Use the <a href="{@docRoot}guide/topics/ui/menus.html#options-menu">Options Menu</a> as an
|
||
alternative to complex touchscreen tasks.</li>
|
||
<li>Make sure the BACK button correctly moves the user back one logical step in the <a
|
||
href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">task's back stack</a> or the
|
||
activity's back stack of fragments (when <a
|
||
href="{@docRoot}guide/topics/fundamentals/fragments.html#Transactions">performing fragment
|
||
transactions</a>), as appropriate.</li>
|
||
</ul>
|
||
|
||
|
||
|
||
<h2 id="CustomViews">Send Accessibility Events from Custom View Components</h2>
|
||
|
||
<p>If your application requires that you create a <a
|
||
href="{@docRoot}guide/topics/ui/custom-components.html">custom view component</a>, you may need to
|
||
do some additional work to ensure that your view is accessible. Specifically, you should make sure
|
||
that your view implements the {@link android.view.accessibility.AccessibilityEventSource}
|
||
interface and emits {@link android.view.accessibility.AccessibilityEvent}s at the proper times,
|
||
and that each {@link android.view.accessibility.AccessibilityEvent} contains relevant information
|
||
about the state of the view.</p>
|
||
|
||
<p>Events are emitted whenever something notable happens in the user interface. Currently, there
|
||
are five types of accessibility events that a view should send to the system as the user interacts
|
||
with it:</p>
|
||
|
||
<dl>
|
||
<dt>{@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED}</dt>
|
||
<dd>Indicates that the user clicked on the view (for example, the user selects a button).</dd>
|
||
|
||
<dt>{@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_LONG_CLICKED}</dt>
|
||
<dd>Indicates that the user performed a long press on the view. </dd>
|
||
|
||
<dt>{@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SELECTED}</dt>
|
||
<dd>Indicates that the user selected an item from within the view. This is usually used in the
|
||
context of an {@link android.widget.AdapterView}.</dd>
|
||
|
||
<dt>{@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_FOCUSED}</dt>
|
||
<dd>Indicates that the user moved the focus to the view.</dd>
|
||
|
||
<dt>{@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED}</dt>
|
||
<dd>Indicates that the text or contents of the view changed.</dd>
|
||
</dl>
|
||
|
||
|
||
<p>The basic {@link android.view.View} class implements {@link
|
||
android.view.accessibility.AccessibilityEventSource} and emits these events at the proper time in
|
||
the standard cases. Your custom view should extend from {@link android.view.View} (or one of its
|
||
subclasses) to take advantage of these default implementations.</p>
|
||
|
||
<p>Depending on the specifics of your custom view, your view may need to emit one of these events at
|
||
a different time than the default {@link android.view.View} implementation. To do so, simply call
|
||
{@link android.view.accessibility.AccessibilityEventSource#sendAccessibilityEvent
|
||
sendAccessibilityEvent()} with the specific event type at the correct time.</p>
|
||
|
||
<p>For example, say you are implementing a custom slider bar that allows the user to select a
|
||
numeric value by pressing the left or right arrows. This view should emit an event of type {@link
|
||
android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED} whenever the slider value
|
||
changes:</p>
|
||
|
||
<pre>
|
||
@Override
|
||
public boolean onKeyUp (int keyCode, KeyEvent event) {
|
||
if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
|
||
mCurrentValue--;
|
||
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
|
||
return true;
|
||
}
|
||
...
|
||
}
|
||
</pre>
|
||
|
||
<p>Each {@link android.view.accessibility.AccessibilityEvent} has a set of required properties that
|
||
describe the current state of the view. These properties include things like the view’s class name,
|
||
text and checked state. The specific properties required for each event type are described in the
|
||
{@link android.view.accessibility.AccessibilityEvent} documentation. The {@link android.view.View}
|
||
implementation will fill in default values for these properties. Most of these values, like the
|
||
class name and event timestamp, will not need to be changed. However, depending on the specifics of
|
||
your custom view, you may want to provide a different value for one or more of the properties. For
|
||
example, your view may have additional state information that you want to add to the event text.</p>
|
||
|
||
<p>The {@link android.view.View#dispatchPopulateAccessibilityEvent
|
||
dispatchPopulateAccessibilityEvent()} method in {@link android.view.View} provides a hook for making
|
||
changes to the {@link android.view.accessibility.AccessibilityEvent} object before it is
|
||
emitted.</p>
|
||
|
||
<p>In the above slider bar example, the view should add the current value of the slider bar to the
|
||
text of the event:</p>
|
||
|
||
<pre>
|
||
@Override
|
||
public boolean dispatchPopulateAccessibilityEvent(final AccessibilityEvent event) {
|
||
super.dispatchPopulateAccessibilityEvent(event);
|
||
if (!isShown()) {
|
||
return false;
|
||
}
|
||
CharSequence text = String.valueOf(mCurrentValue);
|
||
if (text.length() > AccessibilityEvent.MAX_TEXT_LENGTH) {
|
||
text = text.subSequence(0, AccessiblityEvent.MAX_TEXT_LENGTH);
|
||
}
|
||
event.getText().add(text);
|
||
return true;
|
||
}
|
||
</pre>
|
||
|
||
|
||
<h2 id="Test">Test Your Application’s Accessibility</h2>
|
||
|
||
<p>You can simulate the experience for many users by enabling an accessibility service that speaks
|
||
as you move around the screen. One such service is <a
|
||
href="https://market.android.com/details?id=com.google.android.marvin.talkback">TalkBack</a>, by the
|
||
<a href="http://code.google.com/p/eyes-free/">Eyes-Free Project</a>. It comes preinstalled on many
|
||
Android-powered devices, but is also available for free from <a
|
||
href="https://market.android.com/details?id=com.google.android.marvin.talkback">Android
|
||
Market</a>.</p>
|
||
|
||
<p>This service requires that you have a text-to-speech engine installed on your phone. You can
|
||
verify if you have one installed in the <strong>Text-to-speech</strong> settings menu by selecting
|
||
<strong>Listen to an example</strong>. If you do not hear anything spoken, install the required
|
||
voice data by selecting <strong>Install voice data</strong>.</p>
|
||
|
||
<p>Once text-to-speech is functioning correctly, you can enable TalkBack (or another accessibility
|
||
service) in the <strong>Accessibility</strong> settings menu. Enable both
|
||
<strong>Accessibility</strong> and <strong>TalkBack</strong>. As you navigate about the device, you
|
||
should now hear spoken feedback.</p>
|
||
|
||
<p>You can now attempt to use your application as a blind user would. As you move around using only
|
||
the directional controller, make sure that the spoken feedback you hear makes sense and is
|
||
sufficient to navigate the application without any visual cues.</p>
|