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 <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> 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 <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 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/extras/support-library.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 <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 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 @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 @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/extras/support-library.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 @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 536 directly in your custom view class. For another example of this approach, see the Android 537 <a href="{@docRoot}tools/extras/support-library.html">Support Library</a> (revision 5 or higher) 538 sample {@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 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/extras/support-library.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 @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 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