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<ImageButton 122 android:id=”@+id/add_note_button” 123 android:src=”@drawable/add_note” 124 android:contentDescription=”@string/add_note”/> 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<LinearLayout android:orientation="horizontal" 215 ... > 216 <EditText android:id="@+id/edit" 217 android:nextFocusDown=”@+id/text” 218 ... /> 219 <TextView android:id="@+id/text" 220 android:focusable=”true” 221 android:text="Hello, I am a focusable TextView" 222 android:nextFocusUp=”@id/edit” 223 ... /> 224</LinearLayout> 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@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@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 @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 @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 @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 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<p class="note"><strong>Note:</strong> You may find information on implementing accessibility for 542custom views written prior to Android 4.0 that describes the use of the 543{@link android.view.View#dispatchPopulateAccessibilityEvent dispatchPopulateAccessibilityEvent()} 544method for populating AccessibilityEvents. As of the Android 4.0 release, however, the recommended 545approach is to use the 546{@link android.view.View#onPopulateAccessibilityEvent onPopulateAccessibilityEvent()} and 547{@link android.view.View#onInitializeAccessibilityEvent onInitializeAccessibilityEvent()} 548methods.</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 606control 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 608and trigger a special click event. In order to maintain compatibility with accessibility services, 609the 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 620method and then execute whatever actions are required by the click event. When the custom click 621action is detected, that code should then call your {@code performClick()} method. The following 622code example demonstrates this pattern.</p> 623 624<pre> 625class CustomTouchView extends View { 626 627 public CustomTouchView(Context context) { 628 super(context); 629 } 630 631 boolean mDownTouch = false; 632 633 @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 @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 670accessibility services by using the {@link android.view.View#performClick} method to both generate 671an accessibility event and provide an entry point for accessibility services to act on behalf of a 672user 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 675a custom calendar view, you must implement a <a href="#virtual-hierarchy">virtual view 676hierarchy</a> by overriding {@link android.view.View#getAccessibilityNodeProvider} in your custom 677view 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 683great experience. You can test the most important accessibility features by using your application 684with audible feedback enabled and navigating within your application using only directional 685controls. 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