Home | History | Annotate | Download | only in accessibility
      1 page.title=Making Applications Accessible
      2 parent.title=Accessibility
      3 parent.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
     53 limitations when those users activate accessibility services and features on a device. These
     54 services make your application more accessible even if you do not make any accessibility changes
     55 to your code. However, there are steps you should take to optimize the accessibility of your
     56 application 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
     59 when you create your user interface with the components provided by the Android framework. If you
     60 use 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
     83 some additional work to make sure your components are accessible. This document discusses how to
     84 make 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
     88 making your application accessible for users with blindness or low-vision. Be sure to review the
     89 requirements for serving users who are deaf and hard of hearing in the
     90 <a href="{@docRoot}guide/topics/ui/accessibility/checklist.html">Accessibility Developer
     91 Checklist</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
     98 example, a note-taking application might use an {@link android.widget.ImageButton} with a
     99 picture of a plus sign to indicate that the user can add a new note. An {@link
    100 android.widget.EditText} component may have a label near it that indicates its purpose. A user
    101 with 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
    106 appear on screen, but if the user enables accessibility services that provide audible prompts, then
    107 when 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}
    113 in your application's user interface, and add descriptions to any other input controls that might
    114 require 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
    117 the plus button to the {@code add_note} string resource, which could be defined as Add note" for an
    118 English language interface:</p>
    119 
    120 <pre>
    121 &lt;ImageButton
    122     android:id=@+id/add_note_button
    123     android:src=@drawable/add_note
    124     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>
    132 attribute <em>instead</em> of a content description, to help users understand what content is
    133 expected when the text field is empty. When the field is filled, TalkBack reads the entered
    134 content 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
    140 directional controller. Directional controllers can be physical, such as a trackball, directional
    141 pad (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">
    143 Eyes-Free Keyboard</a>, or the gestures navigation mode available in Android 4.1 and higher.
    144 Directional 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
    148 that all user interface (UI) input controls in your application can be reached and activated
    149 without using the touchscreen. You should also verify that clicking with the center button (or OK
    150 button) of a directional controller has the same effect as touching a control that already has
    151 focus. For information on testing directional controls, see
    152 <a href="{@docRoot}tools/testing/testing_accessibility.html#test-navigation">Testing
    153 focus 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
    161 on the element using the directional controls and then interact with it. The user interface controls
    162 provided by the Android framework are focusable by default and visually indicate focus by changing
    163 the controls appearance.</p>
    164 
    165 <p>Android provides several APIs that let you control whether a user interface control is focusable
    166 and 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
    175 the <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
    177 android.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
    183 user interface element (view) to another, as determined by the focus order. This order is based on
    184 an algorithm that finds the nearest neighbor in a given direction. In rare cases, the algorithm may
    185 not match the order that you intended or may not be logical for users. In these situations, you can
    186 provide 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
    206 android:nextFocusDown}</a> and
    207 <a href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusUp">{@code
    208 android:nextFocusUp}</a> attributes have been explicitly set. The {@link android.widget.TextView} is
    209 located to the right of the {@link android.widget.EditText}. However, since these properties have
    210 been set, the {@link android.widget.TextView} element can now be reached by pressing the down arrow
    211 when 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/text
    218         ... /&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/edit
    223         ... /&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
    228 each 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
    231 at runtime, using methods such as {@link android.view.View#setNextFocusDownId setNextFocusDownId()}
    232 and {@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
    238 view component</a>, you must do some additional work to ensure that your custom view is accessible.
    239 These 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
    254 android.view.KeyEvent} with {@link android.view.KeyEvent#KEYCODE_DPAD_CENTER} to the view currently
    255 in focus. All standard Android views already handle {@link
    256 android.view.KeyEvent#KEYCODE_DPAD_CENTER} appropriately. When building a custom {@link
    257 android.view.View} control, make sure this event has the same effect as touching the view on the
    258 touchscreen. </p>
    259 
    260 <p>Your custom control should also treat the {@link android.view.KeyEvent#KEYCODE_ENTER} event the
    261 same as {@link android.view.KeyEvent#KEYCODE_DPAD_CENTER}. This approach makes interaction from a
    262 full 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
    268 your application. These messages are handled by <a href="services.html">Accessibility Services</a>,
    269 which use the information in these events to produce supplemental feedback and prompts. In
    270 Android 4.0 (API Level 14) and higher, the methods for
    271 generating 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
    273 Level 4). The expanded accessibility methods are part of the {@link android.view.View} class as well
    274 as 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
    279 classified with a user action type such as {@link
    280 android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED TYPE_VIEW_CLICKED}. You typically do
    281 not need to implement this method unless you are creating a custom view.</dd>
    282 
    283   <dt>{@link android.view.View#sendAccessibilityEventUnchecked
    284 sendAccessibilityEventUnchecked()}</dt>
    285   <dd>(API Level 4) This method is used when the calling code needs to directly control the check
    286 for accessibility being enabled on the device ({@link
    287 android.view.accessibility.AccessibilityManager#isEnabled AccessibilityManager.isEnabled()}). If
    288 you do implement this method, you must perform the call as if accessibility is enabled, regardless
    289 of 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
    293 dispatchPopulateAccessibilityEvent()}</dt>
    294   <dd>(API Level 4) The system calls this method when your custom view generates an
    295 accessibility event. As of API Level 14, the default implementation of this method calls {@link
    296 android.view.View#onPopulateAccessibilityEvent onPopulateAccessibilityEvent()} for this view and
    297 then the {@link android.view.View#dispatchPopulateAccessibilityEvent
    298 dispatchPopulateAccessibilityEvent()} method for each child of this view. In order to support
    299 accessibility 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
    301 android.view.accessibility.AccessibilityEvent#getText} with descriptive text for your custom
    302 view, 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
    306 android.view.accessibility.AccessibilityEvent} for your view. This method is also called if the
    307 view 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
    310 this method potentially overwrites properties set by other methods. While you can modify
    311 attributes of the accessibility event with this method, you should limit these changes
    312 to text content, and use the {@link android.view.View#onInitializeAccessibilityEvent
    313 onInitializeAccessibilityEvent()} method to modify other properties of the event.</p>
    314 
    315   <p class="note"><strong>Note:</strong> If your implementation of this event completely
    316 overrides the output text without allowing other parts of your layout to modify its content, then
    317 do 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
    322 state of the view, beyond text content. If your custom view provides interactive control beyond a
    323 simple {@link android.widget.TextView} or {@link android.widget.Button}, you should override this
    324 method and set the additional information about your view into the event using this method, such as
    325 password field type, checkbox type or states that provide user interaction or feedback. If you
    326 do override this method, you must call its super implementation and then only modify properties
    327 that have not been set by the super class.</dd>
    328 
    329   <dt>{@link android.view.View#onInitializeAccessibilityNodeInfo
    330 onInitializeAccessibilityNodeInfo()}</dt>
    331   <dd>(API Level 14) This method provides accessibility services with information about the state of
    332 the view. The default {@link android.view.View} implementation has a standard set of view
    333 properties, but if your custom view provides interactive control beyond a simple {@link
    334 android.widget.TextView} or {@link android.widget.Button}, you should override this method and set
    335 the additional information about your view into the {@link
    336 android.view.accessibility.AccessibilityNodeInfo} object handled by this method.</dd>
    337 
    338   <dt>{@link android.view.ViewGroup#onRequestSendAccessibilityEvent
    339 onRequestSendAccessibilityEvent()}</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
    342 the accessibility event with additional information. You should implement this method only if your
    343 custom view can have child views and if the parent view can provide context information to the
    344 accessibility 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
    348 following approaches:</p>
    349 
    350 <ul>
    351   <li>If your application targets Android 4.0 (API level 14) and higher, override and implement the
    352 accessibility 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
    354 the Android <a href="{@docRoot}tools/support-library/index.html">Support Library</a>, revision 5 or
    355 higher, to your project. Then, within your custom view class, call the
    356 {@link android.support.v4.view.ViewCompat#setAccessibilityDelegate
    357 ViewCompat.setAccessibilityDelegate()} method to implement the accessibility methods
    358 above. For an example of this approach, see the Android Support Library (revision 5 or higher)
    359 sample {@code AccessibilityDelegateSupportActivity} in
    360 ({@code &lt;sdk&gt;/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
    365 class:</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
    379 Accessibility 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
    385 android.view.accessibility.AccessibilityEvent} objects at a different times or for events not
    386 handled by the default implementation. The {@link android.view.View} class provides a default
    387 implementation 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
    411 Touch feature, which uses these events as triggers for providing audible prompts for user interface
    412 elements.</p>
    413 
    414 <p>In general, you should send an {@link android.view.accessibility.AccessibilityEvent} whenever the
    415 content of your custom view changes. For example, if you are implementing a custom slider bar that
    416 allows a user to select a numeric value by pressing the left or right arrows, your custom view
    417 should emit an event of type {@link
    418 android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED} whenever the slider
    419 value changes. The following sample code demonstrates the use of the {@link
    420 android.view.accessibility.AccessibilityEventSource#sendAccessibilityEvent
    421 sendAccessibilityEvent()} method to report this event.</p>
    422 
    423 <pre>
    424 &#64;Override
    425 public 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
    439 describe the current state of the view. These properties include things such as the views class
    440 name, content description and checked state. The specific properties required for each event type
    441 are described in the {@link android.view.accessibility.AccessibilityEvent} reference documentation.
    442 The {@link android.view.View} implementation provides default values for these properties. Many of
    443 these values, including the class name and event timestamp, are provided automatically. If you are
    444 creating a custom view component, you must provide some information about the content and
    445 characteristics of the view. This information may be as simple as a button label, but may also
    446 include 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
    449 view is to implement {@link android.view.View#dispatchPopulateAccessibilityEvent
    450 dispatchPopulateAccessibilityEvent()}. This method is called by the system to request
    451 information for an {@link android.view.accessibility.AccessibilityEvent} and makes your custom
    452 view compatible with accessibility services on Android 1.6 (API Level 4) and higher. The
    453 following example code demonstrates a basic implementation of this method.</p>
    454 
    455 <pre>
    456 &#64;Override
    457 public 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
    473 android.view.View#onPopulateAccessibilityEvent onPopulateAccessibilityEvent()} and
    474 {@link android.view.View#onInitializeAccessibilityEvent onInitializeAccessibilityEvent()}
    475 methods to populate or modify the information in an {@link
    476 android.view.accessibility.AccessibilityEvent}. Use the
    477 {@link android.view.View#onPopulateAccessibilityEvent onPopulateAccessibilityEvent()} method
    478 specifically for adding or modifying the text content of the event, which is turned into audible
    479 prompts by accessibility services such as TalkBack. Use the
    480 {@link android.view.View#onInitializeAccessibilityEvent onInitializeAccessibilityEvent()} method for
    481 populating 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()}
    485 method. The {@link android.view.accessibility.AccessibilityNodeInfo} objects populated by this method
    486 are used by accessibility services to investigate the view hierarchy that generated an accessibility
    487 event after receiving that event, to obtain a more detailed context information and provide
    488 appropriate 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
    492 ViewCompat.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
    494 5 or higher) is added to your project.</p>
    495 
    496 <pre>
    497 ViewCompat.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>In applications targeting Android 4.0 (API Level 14) and higher, you can implement these methods
    536 directly 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)
    538 sample {@code AccessibilityDelegateSupportActivity} in
    539 ({@code &lt;sdk&gt;/extras/android/support/v4/samples/Support4Demos/}).</p>
    540 
    541 <p class="note"><strong>Note:</strong> You may find information on implementing accessibility for
    542 custom views written prior to Android 4.0 that describes the use of the
    543 {@link android.view.View#dispatchPopulateAccessibilityEvent dispatchPopulateAccessibilityEvent()}
    544 method for populating AccessibilityEvents. As of the Android 4.0 release, however, the recommended
    545 approach is to use the
    546 {@link android.view.View#onPopulateAccessibilityEvent onPopulateAccessibilityEvent()} and
    547 {@link android.view.View#onInitializeAccessibilityEvent onInitializeAccessibilityEvent()}
    548 methods.</p>
    549 
    550 
    551 <h3 id="virtual-hierarchy">Providing a customized accessibility context</h3>
    552 
    553 <p>In Android 4.0 (API Level 14), the framework was enhanced to allow accessibility services to
    554   inspect the containing view hierarchy of a user interface component that generates an
    555   accessibility event. This enhancement allows accessibility services to provide a much richer set
    556   of contextual information with which to aid users.</p>
    557 
    558 <p>There are some cases where accessibility services cannot get adequate information
    559   from the view hierarchy. An example of this is a custom interface control that has two or more
    560   separately clickable areas, such as a calendar control. In this case, the services cannot get
    561   adequate information because the clickable subsections are not part of the view hierarchy.</p>
    562 
    563 <img src="calendar.png" alt="" id="figure1" />
    564 <p class="img-caption">
    565   <strong>Figure 1.</strong> A custom calendar view with selectable day elements.
    566 </p>
    567 
    568 <p>In the example shown in Figure 1, the entire calendar is implemented as a single view, so if you
    569   do not do anything else, accessibility services do not receive enough information about the
    570   content of the view and the user's selection within the view. For example, if a user clicks on the
    571   day containing <strong>17</strong>, the accessibility framework only receives the description
    572   information for the whole calendar control. In this case, the TalkBack accessibility service would
    573   simply announce "Calendar" or, only slightly better, "April Calendar" and the user would be left
    574   to wonder what day was selected.</p>
    575 
    576 <p>To provide adequate context information for accessibility services in situations like this,
    577   the framework provides a way to specify a virtual view hierarchy. A <em>virtual view
    578   hierarchy</em> is a way for application developers to provide a complementary view hierarchy
    579   to accessibility services that more closely matches the actual information on screen. This
    580   approach allows accessibility services to provide more useful context information to users.</p>
    581 
    582 <p>Another situation where a virtual view hierarchy may be needed is a user interface containing
    583   a set of controls (views) that have closely related functions, where an action on one control
    584   affects the contents of one or more elements, such as a number picker with separate up and down
    585   buttons. In this case, accessibility services cannot get adequate information because action on
    586   one control changes content in another and the relationship of those controls may not be apparent
    587   to the service. To handle this situation, group the related controls with a containing view and
    588   provide a virtual view hierarchy from this container to clearly represent the information and
    589   behavior provided by the controls.</p>
    590 
    591 <p>In order to provide a virtual view hierarchy for a view, override the {@link
    592   android.view.View#getAccessibilityNodeProvider} method in your custom view or view group and
    593   return an implementation of {@link android.view.accessibility.AccessibilityNodeProvider}. For an
    594   example implementation of this accessibility feature, see
    595   {@code AccessibilityNodeProviderActivity} in the ApiDemos sample project. You can implement a
    596   virtual view hierarchy that is compatible with Android 1.6 and later by using the
    597   <a href="{@docRoot}tools/support-library/index.html">Support Library</a> with the
    598   {@link android.support.v4.view.ViewCompat#getAccessibilityNodeProvider
    599   ViewCompat.getAccessibilityNodeProvider()} method and providing an implementation with
    600   {@link android.support.v4.view.accessibility.AccessibilityNodeProviderCompat}.</p>
    601 
    602 
    603 <h3 id="custom-touch-events">Handling custom touch events</h3>
    604 
    605 <p>Custom view controls may require non-standard touch event behavior. For example, a custom
    606 control may use the {@link android.view.View#onTouchEvent} listener method to detect the
    607 {@link android.view.MotionEvent#ACTION_DOWN} and {@link android.view.MotionEvent#ACTION_UP} events
    608 and trigger a special click event. In order to maintain compatibility with accessibility services,
    609 the code that handles this custom click event must do the following:</p>
    610 
    611 <ol>
    612   <li>Generate an appropriate {@link android.view.accessibility.AccessibilityEvent} for the
    613   interpreted click action.</li>
    614   <li>Enable accessibility services to perform the custom click action for users who are not able to
    615    use a touch screen.</li>
    616 </ol>
    617 
    618 <p>To handle these requirements in an efficient way, your code should override the
    619 {@link android.view.View#performClick} method, which must call the super implementation of this
    620 method and then execute whatever actions are required by the click event. When the custom click
    621 action is detected, that code should then call your {@code performClick()} method. The following
    622 code example demonstrates this pattern.</p>
    623 
    624 <pre>
    625 class CustomTouchView extends View {
    626 
    627     public CustomTouchView(Context context) {
    628         super(context);
    629     }
    630 
    631     boolean mDownTouch = false;
    632 
    633     &#64;Override
    634     public boolean onTouchEvent(MotionEvent event) {
    635         super.onTouchEvent(event);
    636 
    637         // Listening for the down and up touch events
    638         switch (event.getAction()) {
    639             case MotionEvent.ACTION_DOWN:
    640                 mDownTouch = true;
    641                 return true;
    642 
    643             case MotionEvent.ACTION_UP:
    644                 if (mDownTouch) {
    645                     mDownTouch = false;
    646                     performClick(); // Call this method to handle the response, and
    647                                     // thereby enable accessibility services to
    648                                     // perform this action for a user who cannot
    649                                     // click the touchscreen.
    650                     return true;
    651                 }
    652         }
    653         return false; // Return false for other touch events
    654     }
    655 
    656     &#64;Override
    657     public boolean performClick() {
    658         // Calls the super implementation, which generates an AccessibilityEvent
    659         // and calls the onClick() listener on the view, if any
    660         super.performClick();
    661 
    662         // Handle the action for the custom click here
    663 
    664         return true;
    665     }
    666 }
    667 </pre>
    668 
    669 <p>The pattern shown above makes sure that the custom click event is compatible with
    670 accessibility services by using the {@link android.view.View#performClick} method to both generate
    671 an accessibility event and provide an entry point for accessibility services to act on behalf of a
    672 user to perform this custom click event.</p>
    673 
    674 <p class="note"><strong>Note:</strong> If your custom view has distinct clickable regions, such as
    675 a custom calendar view, you must implement a <a href="#virtual-hierarchy">virtual view
    676 hierarchy</a> by overriding {@link android.view.View#getAccessibilityNodeProvider} in your custom
    677 view in order to be compatible with accessibility services.</p>
    678 
    679 
    680 <h2 id="test">Testing Accessibility</h2>
    681 
    682 <p>Testing the accessibility of your application is an important part of ensuring your users have a
    683 great experience. You can test the most important accessibility features by using your application
    684 with audible feedback enabled and navigating within your application using only directional
    685 controls. For more information on testing accessibility in your application, see the
    686 <a href="{@docRoot}tools/testing/testing_accessibility.html">Accessibility Testing Checklist</a>.
    687 </p>
    688 
    689