1page.title=Making Applications Accessible
2parent.title=Accessibility
3parent.link=index.html
4@jd:body
5
6<div id="qv-wrapper">
7<div id="qv">
8
9  <h2>In this document</h2>
10  <ol>
11    <li><a href="#label-ui">Labeling User Interface Elements</a></li>
12    <li><a href="#focus-nav">Enabling Focus Navigation</a>
13      <ol>
14        <li><a href="#focus-enable">Enabling view focus</a></li>
15        <li><a href="#focus-order">Controlling focus order</a></li>
16      </ol>
17    </li>
18    <li><a href="#custom-views">Building Accessible Custom Views</a>
19      <ol>
20        <li><a href="#directional-control">Handling directional controller clicks</a></li>
21        <li><a href="#accessibility-methods">Implementing accessibility API methods</a></li>
22        <li><a href="#send-events">Sending accessibility events</a></li>
23        <li><a href="#populate-events">Populating accessibility events</a></li>
24        <li><a href="#virtual-hierarchy">Providing a customized accessibility context</a></li>
25        <li><a href="#custom-touch-events">Handling custom touch events</a></li>
26      </ol>
27    </li>
28    <li><a href="#test">Testing Accessibility</a></li>
29  </ol>
30
31  <h2>Key classes</h2>
32  <ol>
33    <li>{@link android.view.accessibility.AccessibilityEvent}</li>
34    <li>{@link android.view.accessibility.AccessibilityNodeInfo}</li>
35    <li>{@link android.support.v4.view.accessibility.AccessibilityNodeInfoCompat}</li>
36    <li>{@link android.view.View.AccessibilityDelegate}</li>
37    <li>{@link android.support.v4.view.AccessibilityDelegateCompat}</li>
38  </ol>
39
40  <h2>See also</h2>
41  <ol>
42    <li><a href="checklist.html">Accessibility Developer Checklist</a><li>
43    <li><a href="{@docRoot}tools/testing/testing_accessibility.html">Accessibility Testing Checklist</a><li>
44    <li><a href="{@docRoot}design/patterns/accessibility.html">Android Design: Accessibility</a></li>
45    <li><a href="{@docRoot}training/design-navigation/index.html">Designing Effective Navigation</a></li>
46    <li><a href="{@docRoot}training/accessibility/index.html">Training: Implementing Accessibility</a></li>
47  </ol>
48
49</div>
50</div>
51
52<p>Applications built for Android are more accessible to users with visual, physical or age-related
53limitations when those users activate accessibility services and features on a device. These
54services make your application more accessible even if you do not make any accessibility changes
55to your code. However, there are steps you should take to optimize the accessibility of your
56application and ensure a pleasant experience for all your users.</p>
57
58<p>Making sure your application is accessible to all users requires only a few steps, particularly
59when you create your user interface with the components provided by the Android framework. If you
60use only the standard components for your application, the steps are:</p>
61
62<ol>
63  <li>Add descriptive text to user interface controls in your application using the
64    <a href="{@docRoot}reference/android/view/View.html#attr_android:contentDescription">
65    {@code android:contentDescription}</a> attribute. Pay particular attention to
66    {@link android.widget.ImageButton}, {@link android.widget.ImageView}
67    and {@link android.widget.CheckBox}.</li>
68  <li>Make sure that all user interface elements that can accept input (touches or typing) can be
69    reached with a directional controller, such as a trackball, D-pad (physical or virtual) or
70    navigation <a href="http://support.google.com/android/bin/topic.py?hl=en&topic=2492346">gestures
71    </a>.</li>
72  <li>Make sure that audio prompts are always accompanied by another visual prompt or notification,
73    to assist users who are deaf or hard of hearing.</li>
74  <li>Test your application using only accessibility navigation services and features. Turn on
75    <a href="{@docRoot}tools/testing/testing_accessibility.html#testing-talkback">TalkBack</a> and
76    <a href="{@docRoot}tools/testing/testing_accessibility.html#testing-ebt">Explore by Touch</a>,
77    and then try using your application using only directional controls. For more information on
78    testing for accessibility, see the <a href="{@docRoot}tools/testing/testing_accessibility.html">
79    Accessibility Testing Checklist</a>.</li>
80</ol>
81
82<p>If you build custom controls that extend the {@link android.view.View} class, you must complete
83some additional work to make sure your components are accessible. This document discusses how to
84make custom view controls compatible with accessibility services.</p>
85
86<p class="note">
87<strong>Note:</strong> The implementation steps in this document describe the requirements for
88making your application accessible for users with blindness or low-vision. Be sure to review the
89requirements for serving users who are deaf and hard of hearing in the
90<a href="{@docRoot}guide/topics/ui/accessibility/checklist.html">Accessibility Developer
91Checklist</a></p>.
92
93
94
95<h2 id="label-ui">Labeling User Interface Elements</h2>
96
97<p>Many user interface controls depend on visual cues to indicate their meaning and usage. For
98example, a note-taking application might use an {@link android.widget.ImageButton} with a
99picture of a plus sign to indicate that the user can add a new note. An {@link
100android.widget.EditText} component may have a label near it that indicates its purpose. A user
101with impaired vision can't see these cues well enough to follow them, which makes them useless.</p>
102
103<p>You can make these controls more accessible with the
104<a href="{@docRoot}reference/android/view/View.html#attr_android:contentDescription">
105{@code android:contentDescription}</a> XML layout attribute. The text in this attribute does not
106appear on screen, but if the user enables accessibility services that provide audible prompts, then
107when the user navigates to that control, the text is spoken.</p>
108
109<p>For this reason, set the
110<a href="{@docRoot}reference/android/view/View.html#attr_android:contentDescription">
111{@code android:contentDescription}</a> attribute for every {@link android.widget.ImageButton},
112{@link android.widget.ImageView}, {@link android.widget.CheckBox}
113in your application's user interface, and add descriptions to any other input controls that might
114require additional information for users who are not able to see it.</p>
115
116<p>For example, the following {@link android.widget.ImageButton} sets the content description for
117the plus button to the {@code add_note} string resource, which could be defined as “Add note" for an
118English language interface:</p>
119
120<pre>
121&lt;ImageButton
122    android:id=”@+id/add_note_button123    android:src=”@drawable/add_note124    android:contentDescription=”@string/add_note”/&gt;
125</pre>
126
127<p>By including the description, an accessibility service that provides spoken feedback can announce
128"Add note" when a user moves focus to this button or hovers over it.</p>
129
130<p class="note"><strong>Note:</strong> For {@link android.widget.EditText} fields, provide an
131<a href="{@docRoot}reference/android/widget/TextView.html#attr_android:hint">android:hint</a>
132attribute <em>instead</em> of a content description, to help users understand what content is
133expected when the text field is empty. When the field is filled, TalkBack reads the entered
134content to the user, instead of the hint text.</p>
135
136
137<h2 id="focus-nav">Enabling Focus Navigation</h2>
138
139<p>Focus navigation allows users with disabilities to step through user interface controls using a
140directional controller. Directional controllers can be physical, such as a trackball, directional
141pad (D-pad) or arrow keys, or virtual, such as the
142<a href="https://play.google.com/store/apps/details?id=com.googlecode.eyesfree.inputmethod.latin">
143Eyes-Free Keyboard</a>, or the gestures navigation mode available in Android 4.1 and higher.
144Directional controllers are a primary means of navigation for many Android users.
145</p>
146
147<p>To ensure that users can navigate your application using only a directional controller, verify
148that all user interface (UI) input controls in your application can be reached and activated
149without using the touchscreen. You should also verify that clicking with the center button (or OK
150button) of a directional controller has the same effect as touching a control that already has
151focus. For information on testing directional controls, see
152<a href="{@docRoot}tools/testing/testing_accessibility.html#test-navigation">Testing
153focus navigation</a>.</p>
154
155
156<h3 id="focus-enable">Enabling view focus</h3>
157
158<p>A user interface element is reachable using directional controls when its
159<a href="{@docRoot}reference/android/view/View.html#attr_android:focusable">
160{@code android:focusable}</a> attribute is set to {@code true}. This setting allows users to focus
161on the element using the directional controls and then interact with it. The user interface controls
162provided by the Android framework are focusable by default and visually indicate focus by changing
163the control’s appearance.</p>
164
165<p>Android provides several APIs that let you control whether a user interface control is focusable
166and even request that a control be given focus:</p>
167
168<ul>
169  <li>{@link android.view.View#setFocusable setFocusable()}</li>
170  <li>{@link android.view.View#isFocusable isFocusable()}</li>
171  <li>{@link android.view.View#requestFocus requestFocus()}</li>
172</ul>
173
174<p>If a view is not focusable by default, you can make it focusable in your layout file by setting
175the <a href="{@docRoot}reference/android/view/View.html#attr_android:focusable">
176{@code android:focusable}</a> attribute to {@code true} or by calling the its {@link
177android.view.View#setFocusable setFocusable()} method.</p>
178
179
180<h3 id="focus-order">Controlling focus order</h3>
181
182<p>When users navigate in any direction using directional controls, focus is passed from one
183user interface element (view) to another, as determined by the focus order. This order is based on
184an algorithm that finds the nearest neighbor in a given direction. In rare cases, the algorithm may
185not match the order that you intended or may not be logical for users. In these situations, you can
186provide explicit overrides to the ordering using the following XML attributes in your layout file:
187</p>
188
189<dl>
190  <dt><a href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusDown">
191  {@code android:nextFocusDown}</a></dt>
192    <dd>Defines the next view to receive focus when the user navigates down.</dd>
193  <dt><a href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusLeft">
194  {@code android:nextFocusLeft}</a></dt>
195    <dd>Defines the next view to receive focus when the user navigates left.</dd>
196  <dt><a href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusRight">
197  {@code android:nextFocusRight}</a></dt>
198    <dd>Defines the next view to receive focus when the user navigates right.</dd>
199  <dt><a href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusUp">
200  {@code android:nextFocusUp}</a></dt>
201    <dd>Defines the next view to receive focus when the user navigates up.</dd>
202</dl>
203
204<p>The following example XML layout shows two focusable user interface elements where the
205<a href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusDown">{@code
206android:nextFocusDown}</a> and
207<a href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusUp">{@code
208android:nextFocusUp}</a> attributes have been explicitly set. The {@link android.widget.TextView} is
209located to the right of the {@link android.widget.EditText}. However, since these properties have
210been set, the {@link android.widget.TextView} element can now be reached by pressing the down arrow
211when focus is on the {@link android.widget.EditText} element:</p>
212
213<pre>
214&lt;LinearLayout android:orientation="horizontal"
215        ... &gt;
216    &lt;EditText android:id="@+id/edit"
217        android:nextFocusDown=”@+id/text218        ... /&gt;
219    &lt;TextView android:id="@+id/text"
220        android:focusable=”true”
221        android:text="Hello, I am a focusable TextView"
222        android:nextFocusUp=”@id/edit223        ... /&gt;
224&lt;/LinearLayout&gt;
225</pre>
226
227<p>When modifying focus order, be sure that the navigation works as expected in all directions from
228each user interface control and when navigating in reverse (to get back to where you came from).</p>
229
230<p class="note"><strong>Note:</strong> You can modify the focus order of user interface components
231at runtime, using methods such as {@link android.view.View#setNextFocusDownId setNextFocusDownId()}
232and {@link android.view.View#setNextFocusRightId setNextFocusRightId()}.</p>
233
234
235<h2 id="custom-views">Building Accessible Custom Views</h2>
236
237<p>If your application requires a <a href="{@docRoot}guide/topics/ui/custom-components.html">custom
238view component</a>, you must do some additional work to ensure that your custom view is accessible.
239These are the main tasks for ensuring the accessibility of your view:</p>
240
241<ul>
242  <li>Handle directional controller clicks</li>
243  <li>Implement accessibility API methods</li>
244  <li>Send {@link android.view.accessibility.AccessibilityEvent} objects specific to your custom
245    view</li>
246  <li>Populate {@link android.view.accessibility.AccessibilityEvent} and {@link
247    android.view.accessibility.AccessibilityNodeInfo} for your view</li>
248</ul>
249
250
251<h3 id="directional-control">Handling directional controller clicks</h3>
252
253<p>On most devices, clicking a view using a directional controller sends a {@link
254android.view.KeyEvent} with {@link android.view.KeyEvent#KEYCODE_DPAD_CENTER} to the view currently
255in focus. All standard Android views already handle {@link
256android.view.KeyEvent#KEYCODE_DPAD_CENTER} appropriately. When building a custom {@link
257android.view.View} control, make sure this event has the same effect as touching the view on the
258touchscreen. </p>
259
260<p>Your custom control should also treat the {@link android.view.KeyEvent#KEYCODE_ENTER} event the
261same as {@link android.view.KeyEvent#KEYCODE_DPAD_CENTER}. This approach makes interaction from a
262full keyboard much easier for users.</p>
263
264
265<h3 id="accessibility-methods">Implementing accessibility API methods</h3>
266
267<p>Accessibility events are messages about users interaction with visual interface components in
268your application. These messages are handled by <a href="services.html">Accessibility Services</a>,
269which use the information in these events to produce supplemental feedback and prompts. In
270Android 4.0 (API Level 14) and higher, the methods for
271generating accessibility events have been expanded to provide more detailed information than the
272{@link android.view.accessibility.AccessibilityEventSource} interface introduced in Android 1.6 (API
273Level 4). The expanded accessibility methods are part of the {@link android.view.View} class as well
274as the {@link android.view.View.AccessibilityDelegate} class. The methods are as follows:</p>
275
276<dl>
277 <dt>{@link android.view.View#sendAccessibilityEvent sendAccessibilityEvent()}</dt>
278  <dd>(API Level 4) This method is called when a user takes action on a view. The event is
279classified with a user action type such as {@link
280android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED TYPE_VIEW_CLICKED}. You typically do
281not need to implement this method unless you are creating a custom view.</dd>
282
283  <dt>{@link android.view.View#sendAccessibilityEventUnchecked
284sendAccessibilityEventUnchecked()}</dt>
285  <dd>(API Level 4) This method is used when the calling code needs to directly control the check
286for accessibility being enabled on the device ({@link
287android.view.accessibility.AccessibilityManager#isEnabled AccessibilityManager.isEnabled()}). If
288you do implement this method, you must perform the call as if accessibility is enabled, regardless
289of the actual system setting. You typically do not need to implement this method for a custom view.
290</dd>
291
292  <dt>{@link android.view.View#dispatchPopulateAccessibilityEvent
293dispatchPopulateAccessibilityEvent()}</dt>
294  <dd>(API Level 4) The system calls this method when your custom view generates an
295accessibility event. As of API Level 14, the default implementation of this method calls {@link
296android.view.View#onPopulateAccessibilityEvent onPopulateAccessibilityEvent()} for this view and
297then the {@link android.view.View#dispatchPopulateAccessibilityEvent
298dispatchPopulateAccessibilityEvent()} method for each child of this view. In order to support
299accessibility services on revisions of Android <em>prior</em> to 4.0 (API Level 14) you
300<em>must</em> override this method and populate {@link
301android.view.accessibility.AccessibilityEvent#getText} with descriptive text for your custom
302view, which is spoken by accessibility services, such as TalkBack.</dd>
303
304  <dt>{@link android.view.View#onPopulateAccessibilityEvent onPopulateAccessibilityEvent()}</dt>
305  <dd>(API Level 14) This method sets the spoken text prompt of the {@link
306android.view.accessibility.AccessibilityEvent} for your view. This method is also called if the
307view is a child of a view which generates an accessibility event.
308
309  <p class="note"><strong>Note:</strong> Modifying additional attributes beyond the text within
310this method potentially overwrites properties set by other methods. While you can modify
311attributes of the accessibility event with this method, you should limit these changes
312to text content, and use the {@link android.view.View#onInitializeAccessibilityEvent
313onInitializeAccessibilityEvent()} method to modify other properties of the event.</p>
314
315  <p class="note"><strong>Note:</strong> If your implementation of this event completely
316overrides the output text without allowing other parts of your layout to modify its content, then
317do not call the super implementation of this method in your code.</p>
318  </dd>
319
320  <dt>{@link android.view.View#onInitializeAccessibilityEvent onInitializeAccessibilityEvent()}</dt>
321  <dd>(API Level 14) The system calls this method to obtain additional information about the
322state of the view, beyond text content. If your custom view provides interactive control beyond a
323simple {@link android.widget.TextView} or {@link android.widget.Button}, you should override this
324method and set the additional information about your view into the event using this method, such as
325password field type, checkbox type or states that provide user interaction or feedback. If you
326do override this method, you must call its super implementation and then only modify properties
327that have not been set by the super class.</dd>
328
329  <dt>{@link android.view.View#onInitializeAccessibilityNodeInfo
330onInitializeAccessibilityNodeInfo()}</dt>
331  <dd>(API Level 14) This method provides accessibility services with information about the state of
332the view. The default {@link android.view.View} implementation has a standard set of view
333properties, but if your custom view provides interactive control beyond a simple {@link
334android.widget.TextView} or {@link android.widget.Button}, you should override this method and set
335the additional information about your view into the {@link
336android.view.accessibility.AccessibilityNodeInfo} object handled by this method.</dd>
337
338  <dt>{@link android.view.ViewGroup#onRequestSendAccessibilityEvent
339onRequestSendAccessibilityEvent()}</dt>
340  <dd>(API Level 14) The system calls this method when a child of your view has generated an
341{@link android.view.accessibility.AccessibilityEvent}. This step allows the parent view to amend
342the accessibility event with additional information. You should implement this method only if your
343custom view can have child views and if the parent view can provide context information to the
344accessibility event that would be useful to accessibility services.</dd>
345</dl>
346
347<p>In order to support these accessibility methods for a custom view, you should take one of the
348following approaches:</p>
349
350<ul>
351  <li>If your application targets Android 4.0 (API level 14) and higher, override and implement the
352accessibility methods listed above directly in your custom view class.</li>
353  <li>If your custom view is intended to be compatible with Android 1.6 (API Level 4) and above, add
354the Android <a href="{@docRoot}tools/support-library/index.html">Support Library</a>, revision 5 or
355higher, to your project. Then, within your custom view class, call the
356{@link android.support.v4.view.ViewCompat#setAccessibilityDelegate
357ViewCompat.setAccessibilityDelegate()} method to implement the accessibility methods
358above. For an example of this approach, see the Android Support Library (revision 5 or higher)
359sample {@code AccessibilityDelegateSupportActivity} in
360({@code <sdk>/extras/android/support/v4/samples/Support4Demos/})
361  </li>
362</ul>
363
364<p>In either case, you should implement the following accessibility methods for your custom view
365class:</p>
366
367<ul>
368  <li>{@link android.view.View#dispatchPopulateAccessibilityEvent
369    dispatchPopulateAccessibilityEvent()}</li>
370  <li>{@link android.view.View#onPopulateAccessibilityEvent
371    onPopulateAccessibilityEvent()}</li>
372  <li>{@link android.view.View#onInitializeAccessibilityEvent
373    onInitializeAccessibilityEvent()}</li>
374  <li>{@link android.view.View#onInitializeAccessibilityNodeInfo
375    onInitializeAccessibilityNodeInfo()}</li>
376</ul>
377
378<p>For more information about implementing these methods, see <a href="#populate-events">Populating
379Accessibility Events</a>.</p>
380
381
382<h3 id="send-events">Sending accessibility events</h3>
383
384<p>Depending on the specifics of your custom view, it may need to send {@link
385android.view.accessibility.AccessibilityEvent} objects at a different times or for events not
386handled by the default implementation. The {@link android.view.View} class provides a default
387implementation for these event types:</p>
388
389<ul>
390  <li>Starting with API Level 4:
391    <ul>
392      <li>{@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED}</li>
393
394      <li>{@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_LONG_CLICKED}</li>
395
396      <li>{@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_FOCUSED}</li>
397    </ul>
398  </li>
399  <li>Starting with API Level 14:
400    <ul>
401      <li>{@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SCROLLED}</li>
402
403      <li>{@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}</li>
404
405      <li>{@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_EXIT}</li>
406    </ul>
407  </li>
408</ul>
409
410<p class="note"><strong>Note:</strong> Hover events are associated with the Explore by
411Touch feature, which uses these events as triggers for providing audible prompts for user interface
412elements.</p>
413
414<p>In general, you should send an {@link android.view.accessibility.AccessibilityEvent} whenever the
415content of your custom view changes. For example, if you are implementing a custom slider bar that
416allows a user to select a numeric value by pressing the left or right arrows, your custom view
417should emit an event of type {@link
418android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED} whenever the slider
419value changes. The following sample code demonstrates the use of the {@link
420android.view.accessibility.AccessibilityEventSource#sendAccessibilityEvent
421sendAccessibilityEvent()} method to report this event.</p>
422
423<pre>
424&#64;Override
425public boolean onKeyUp (int keyCode, KeyEvent event) {
426    if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
427        mCurrentValue--;
428        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
429        return true;
430    }
431    ...
432}
433</pre>
434
435
436<h3 id="populate-events">Populating accessibility events</h3>
437
438<p>Each {@link android.view.accessibility.AccessibilityEvent} has a set of required properties that
439describe the current state of the view. These properties include things such as the view’s class
440name, content description and checked state. The specific properties required for each event type
441are described in the {@link android.view.accessibility.AccessibilityEvent} reference documentation.
442The {@link android.view.View} implementation provides default values for these properties. Many of
443these values, including the class name and event timestamp, are provided automatically. If you are
444creating a custom view component, you must provide some information about the content and
445characteristics of the view. This information may be as simple as a button label, but may also
446include additional state information that you want to add to the event.</p>
447
448<p>The minimum requirement for providing information to accessibility services with a custom
449view is to implement {@link android.view.View#dispatchPopulateAccessibilityEvent
450dispatchPopulateAccessibilityEvent()}. This method is called by the system to request
451information for an {@link android.view.accessibility.AccessibilityEvent} and makes your custom
452view compatible with accessibility services on Android 1.6 (API Level 4) and higher. The
453following example code demonstrates a basic implementation of this method.</p>
454
455<pre>
456&#64;Override
457public void dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
458    super.dispatchPopulateAccessibilityEvent(event);
459    // Call the super implementation to populate its text to the event, which
460    // calls onPopulateAccessibilityEvent() on API Level 14 and up.
461
462    // In case this is running on a API revision earlier that 14, check
463    // the text content of the event and add an appropriate text
464    // description for this custom view:
465    CharSequence text = getText();
466    if (!TextUtils.isEmpty(text)) {
467        event.getText().add(text);
468    }
469}
470</pre>
471
472<p>For Android 4.0 (API Level 14) and higher, use the {@link
473android.view.View#onPopulateAccessibilityEvent onPopulateAccessibilityEvent()} and
474{@link android.view.View#onInitializeAccessibilityEvent onInitializeAccessibilityEvent()}
475methods to populate or modify the information in an {@link
476android.view.accessibility.AccessibilityEvent}. Use the
477{@link android.view.View#onPopulateAccessibilityEvent onPopulateAccessibilityEvent()} method
478specifically for adding or modifying the text content of the event, which is turned into audible
479prompts by accessibility services such as TalkBack. Use the
480{@link android.view.View#onInitializeAccessibilityEvent onInitializeAccessibilityEvent()} method for
481populating additional information about the event, such as the selection state of the view.</p>
482
483<p>In addition, implement the
484{@link android.view.View#onInitializeAccessibilityNodeInfo onInitializeAccessibilityNodeInfo()}
485method. The {@link android.view.accessibility.AccessibilityNodeInfo} objects populated by this method
486are used by accessibility services to investigate the view hierarchy that generated an accessibility
487event after receiving that event, to obtain a more detailed context information and provide
488appropriate feedback to users.</p>
489
490<p>The example code below shows how override these three methods by using
491{@link android.support.v4.view.ViewCompat#setAccessibilityDelegate
492ViewCompat.setAccessibilityDelegate()}. Note that this sample code requires that the Android
493<a href="{@docRoot}tools/support-library/index.html">Support Library</a> for API Level 4 (revision
4945 or higher) is added to your project.</p>
495
496<pre>
497ViewCompat.setAccessibilityDelegate(new AccessibilityDelegateCompat() {
498    &#64;Override
499    public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
500        super.onPopulateAccessibilityEvent(host, event);
501        // We call the super implementation to populate its text for the
502        // event. Then we add our text not present in a super class.
503        // Very often you only need to add the text for the custom view.
504        CharSequence text = getText();
505        if (!TextUtils.isEmpty(text)) {
506            event.getText().add(text);
507        }
508    }
509    &#64;Override
510    public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
511        super.onInitializeAccessibilityEvent(host, event);
512        // We call the super implementation to let super classes
513        // set appropriate event properties. Then we add the new property
514        // (checked) which is not supported by a super class.
515        event.setChecked(isChecked());
516    }
517    &#64;Override
518    public void onInitializeAccessibilityNodeInfo(View host,
519            AccessibilityNodeInfoCompat info) {
520        super.onInitializeAccessibilityNodeInfo(host, info);
521        // We call the super implementation to let super classes set
522        // appropriate info properties. Then we add our properties
523        // (checkable and checked) which are not supported by a super class.
524        info.setCheckable(true);
525        info.setChecked(isChecked());
526        // Quite often you only need to add the text for the custom view.
527        CharSequence text = getText();
528        if (!TextUtils.isEmpty(text)) {
529            info.setText(text);
530        }
531    }
532}
533</pre>
534
535<p>You can implement these methods
536directly in your custom view class. For another example of this approach, see the Android
537<a href="{@docRoot}tools/support-library/index.html">Support Library</a> (revision 5 or higher)
538sample {@code AccessibilityDelegateSupportActivity} in
539({@code <sdk>/extras/android/support/v4/samples/Support4Demos/}).</p>
540
541
542<h3 id="virtual-hierarchy">Providing a customized accessibility context</h3>
543
544<p>In Android 4.0 (API Level 14), the framework was enhanced to allow accessibility services to
545  inspect the containing view hierarchy of a user interface component that generates an
546  accessibility event. This enhancement allows accessibility services to provide a much richer set
547  of contextual information with which to aid users.</p>
548
549<p>There are some cases where accessibility services cannot get adequate information
550  from the view hierarchy. An example of this is a custom interface control that has two or more
551  separately clickable areas, such as a calendar control. In this case, the services cannot get
552  adequate information because the clickable subsections are not part of the view hierarchy.</p>
553
554<img src="calendar.png" alt="" id="figure1" />
555<p class="img-caption">
556  <strong>Figure 1.</strong> A custom calendar view with selectable day elements.
557</p>
558
559<p>In the example shown in Figure 1, the entire calendar is implemented as a single view, so if you
560  do not do anything else, accessibility services do not receive enough information about the
561  content of the view and the user's selection within the view. For example, if a user clicks on the
562  day containing <strong>17</strong>, the accessibility framework only receives the description
563  information for the whole calendar control. In this case, the TalkBack accessibility service would
564  simply announce "Calendar" or, only slightly better, "April Calendar" and the user would be left
565  to wonder what day was selected.</p>
566
567<p>To provide adequate context information for accessibility services in situations like this,
568  the framework provides a way to specify a virtual view hierarchy. A <em>virtual view
569  hierarchy</em> is a way for application developers to provide a complementary view hierarchy
570  to accessibility services that more closely matches the actual information on screen. This
571  approach allows accessibility services to provide more useful context information to users.</p>
572
573<p>Another situation where a virtual view hierarchy may be needed is a user interface containing
574  a set of controls (views) that have closely related functions, where an action on one control
575  affects the contents of one or more elements, such as a number picker with separate up and down
576  buttons. In this case, accessibility services cannot get adequate information because action on
577  one control changes content in another and the relationship of those controls may not be apparent
578  to the service. To handle this situation, group the related controls with a containing view and
579  provide a virtual view hierarchy from this container to clearly represent the information and
580  behavior provided by the controls.</p>
581
582<p>In order to provide a virtual view hierarchy for a view, override the {@link
583  android.view.View#getAccessibilityNodeProvider} method in your custom view or view group and
584  return an implementation of {@link android.view.accessibility.AccessibilityNodeProvider}. For an
585  example implementation of this accessibility feature, see
586  {@code AccessibilityNodeProviderActivity} in the ApiDemos sample project. You can implement a
587  virtual view hierarchy that is compatible with Android 1.6 and later by using the
588  <a href="{@docRoot}tools/support-library/index.html">Support Library</a> with the
589  {@link android.support.v4.view.ViewCompat#getAccessibilityNodeProvider
590  ViewCompat.getAccessibilityNodeProvider()} method and providing an implementation with
591  {@link android.support.v4.view.accessibility.AccessibilityNodeProviderCompat}.</p>
592
593
594<h3 id="custom-touch-events">Handling custom touch events</h3>
595
596<p>Custom view controls may require non-standard touch event behavior. For example, a custom
597control may use the {@link android.view.View#onTouchEvent} listener method to detect the
598{@link android.view.MotionEvent#ACTION_DOWN} and {@link android.view.MotionEvent#ACTION_UP} events
599and trigger a special click event. In order to maintain compatibility with accessibility services,
600the code that handles this custom click event must do the following:</p>
601
602<ol>
603  <li>Generate an appropriate {@link android.view.accessibility.AccessibilityEvent} for the
604  interpreted click action.</li>
605  <li>Enable accessibility services to perform the custom click action for users who are not able to
606   use a touch screen.</li>
607</ol>
608
609<p>To handle these requirements in an efficient way, your code should override the
610{@link android.view.View#performClick} method, which must call the super implementation of this
611method and then execute whatever actions are required by the click event. When the custom click
612action is detected, that code should then call your {@code performClick()} method. The following
613code example demonstrates this pattern.</p>
614
615<pre>
616class CustomTouchView extends View {
617
618    public CustomTouchView(Context context) {
619        super(context);
620    }
621
622    boolean mDownTouch = false;
623
624    &#64;Override
625    public boolean onTouchEvent(MotionEvent event) {
626        super.onTouchEvent(event);
627
628        // Listening for the down and up touch events
629        switch (event.getAction()) {
630            case MotionEvent.ACTION_DOWN:
631                mDownTouch = true;
632                return true;
633
634            case MotionEvent.ACTION_UP:
635                if (mDownTouch) {
636                    mDownTouch = false;
637                    performClick(); // Call this method to handle the response, and
638                                    // thereby enable accessibility services to
639                                    // perform this action for a user who cannot
640                                    // click the touchscreen.
641                    return true;
642                }
643        }
644        return false; // Return false for other touch events
645    }
646
647    &#64;Override
648    public boolean performClick() {
649        // Calls the super implementation, which generates an AccessibilityEvent
650        // and calls the onClick() listener on the view, if any
651        super.performClick();
652
653        // Handle the action for the custom click here
654
655        return true;
656    }
657}
658</pre>
659
660<p>The pattern shown above makes sure that the custom click event is compatible with
661accessibility services by using the {@link android.view.View#performClick} method to both generate
662an accessibility event and provide an entry point for accessibility services to act on behalf of a
663user to perform this custom click event.</p>
664
665<p class="note"><strong>Note:</strong> If your custom view has distinct clickable regions, such as
666a custom calendar view, you must implement a <a href="#virtual-hierarchy">virtual view
667hierarchy</a> by overriding {@link android.view.View#getAccessibilityNodeProvider} in your custom
668view in order to be compatible with accessibility services.</p>
669
670
671<h2 id="test">Testing Accessibility</h2>
672
673<p>Testing the accessibility of your application is an important part of ensuring your users have a
674great experience. You can test the most important accessibility features by using your application
675with audible feedback enabled and navigating within your application using only directional
676controls. For more information on testing accessibility in your application, see the
677<a href="{@docRoot}tools/testing/testing_accessibility.html">Accessibility Testing Checklist</a>.
678</p>
679
680