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 control's 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.AccessibilityRecord#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 <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 view's 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 boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 458 // Call the super implementation to populate its text to the event, which 459 // calls onPopulateAccessibilityEvent() on API Level 14 and up. 460 boolean completed = super.dispatchPopulateAccessibilityEvent(event); 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 return true; 469 } 470 return completed; 471 } 472 </pre> 473 474 <p>For Android 4.0 (API Level 14) and higher, use the {@link 475 android.view.View#onPopulateAccessibilityEvent onPopulateAccessibilityEvent()} and 476 {@link android.view.View#onInitializeAccessibilityEvent onInitializeAccessibilityEvent()} 477 methods to populate or modify the information in an {@link 478 android.view.accessibility.AccessibilityEvent}. Use the 479 {@link android.view.View#onPopulateAccessibilityEvent onPopulateAccessibilityEvent()} method 480 specifically for adding or modifying the text content of the event, which is turned into audible 481 prompts by accessibility services such as TalkBack. Use the 482 {@link android.view.View#onInitializeAccessibilityEvent onInitializeAccessibilityEvent()} method for 483 populating additional information about the event, such as the selection state of the view.</p> 484 485 <p>In addition, implement the 486 {@link android.view.View#onInitializeAccessibilityNodeInfo onInitializeAccessibilityNodeInfo()} 487 method. The {@link android.view.accessibility.AccessibilityNodeInfo} objects populated by this method 488 are used by accessibility services to investigate the view hierarchy that generated an accessibility 489 event after receiving that event, to obtain a more detailed context information and provide 490 appropriate feedback to users.</p> 491 492 <p>The example code below shows how override these three methods by using 493 {@link android.support.v4.view.ViewCompat#setAccessibilityDelegate 494 ViewCompat.setAccessibilityDelegate()}. Note that this sample code requires that the Android 495 <a href="{@docRoot}tools/support-library/index.html">Support Library</a> for API Level 4 (revision 496 5 or higher) is added to your project.</p> 497 498 <pre> 499 ViewCompat.setAccessibilityDelegate(new AccessibilityDelegateCompat() { 500 @Override 501 public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) { 502 super.onPopulateAccessibilityEvent(host, event); 503 // We call the super implementation to populate its text for the 504 // event. Then we add our text not present in a super class. 505 // Very often you only need to add the text for the custom view. 506 CharSequence text = getText(); 507 if (!TextUtils.isEmpty(text)) { 508 event.getText().add(text); 509 } 510 } 511 @Override 512 public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { 513 super.onInitializeAccessibilityEvent(host, event); 514 // We call the super implementation to let super classes 515 // set appropriate event properties. Then we add the new property 516 // (checked) which is not supported by a super class. 517 event.setChecked(isChecked()); 518 } 519 @Override 520 public void onInitializeAccessibilityNodeInfo(View host, 521 AccessibilityNodeInfoCompat info) { 522 super.onInitializeAccessibilityNodeInfo(host, info); 523 // We call the super implementation to let super classes set 524 // appropriate info properties. Then we add our properties 525 // (checkable and checked) which are not supported by a super class. 526 info.setCheckable(true); 527 info.setChecked(isChecked()); 528 // Quite often you only need to add the text for the custom view. 529 CharSequence text = getText(); 530 if (!TextUtils.isEmpty(text)) { 531 info.setText(text); 532 } 533 } 534 } 535 </pre> 536 537 <p>You can implement these methods 538 directly in your custom view class. For another example of this approach, see the Android 539 <a href="{@docRoot}tools/support-library/index.html">Support Library</a> (revision 5 or higher) 540 sample {@code AccessibilityDelegateSupportActivity} in 541 ({@code <sdk>/extras/android/support/v4/samples/Support4Demos/}).</p> 542 543 544 <h3 id="virtual-hierarchy">Providing a customized accessibility context</h3> 545 546 <p>In Android 4.0 (API Level 14), the framework was enhanced to allow accessibility services to 547 inspect the containing view hierarchy of a user interface component that generates an 548 accessibility event. This enhancement allows accessibility services to provide a much richer set 549 of contextual information with which to aid users.</p> 550 551 <p>There are some cases where accessibility services cannot get adequate information 552 from the view hierarchy. An example of this is a custom interface control that has two or more 553 separately clickable areas, such as a calendar control. In this case, the services cannot get 554 adequate information because the clickable subsections are not part of the view hierarchy.</p> 555 556 <img src="calendar.png" alt="" id="figure1" /> 557 <p class="img-caption"> 558 <strong>Figure 1.</strong> A custom calendar view with selectable day elements. 559 </p> 560 561 <p>In the example shown in Figure 1, the entire calendar is implemented as a single view, so if you 562 do not do anything else, accessibility services do not receive enough information about the 563 content of the view and the user's selection within the view. For example, if a user clicks on the 564 day containing <strong>17</strong>, the accessibility framework only receives the description 565 information for the whole calendar control. In this case, the TalkBack accessibility service would 566 simply announce "Calendar" or, only slightly better, "April Calendar" and the user would be left 567 to wonder what day was selected.</p> 568 569 <p>To provide adequate context information for accessibility services in situations like this, 570 the framework provides a way to specify a virtual view hierarchy. A <em>virtual view 571 hierarchy</em> is a way for application developers to provide a complementary view hierarchy 572 to accessibility services that more closely matches the actual information on screen. This 573 approach allows accessibility services to provide more useful context information to users.</p> 574 575 <p>Another situation where a virtual view hierarchy may be needed is a user interface containing 576 a set of controls (views) that have closely related functions, where an action on one control 577 affects the contents of one or more elements, such as a number picker with separate up and down 578 buttons. In this case, accessibility services cannot get adequate information because action on 579 one control changes content in another and the relationship of those controls may not be apparent 580 to the service. To handle this situation, group the related controls with a containing view and 581 provide a virtual view hierarchy from this container to clearly represent the information and 582 behavior provided by the controls.</p> 583 584 <p>In order to provide a virtual view hierarchy for a view, override the {@link 585 android.view.View#getAccessibilityNodeProvider} method in your custom view or view group and 586 return an implementation of {@link android.view.accessibility.AccessibilityNodeProvider}. For an 587 example implementation of this accessibility feature, see 588 {@code AccessibilityNodeProviderActivity} in the ApiDemos sample project. You can implement a 589 virtual view hierarchy that is compatible with Android 1.6 and later by using the 590 <a href="{@docRoot}tools/support-library/index.html">Support Library</a> with the 591 {@link android.support.v4.view.ViewCompat#getAccessibilityNodeProvider 592 ViewCompat.getAccessibilityNodeProvider()} method and providing an implementation with 593 {@link android.support.v4.view.accessibility.AccessibilityNodeProviderCompat}.</p> 594 595 596 <h3 id="custom-touch-events">Handling custom touch events</h3> 597 598 <p>Custom view controls may require non-standard touch event behavior. For example, a custom 599 control may use the {@link android.view.View#onTouchEvent} listener method to detect the 600 {@link android.view.MotionEvent#ACTION_DOWN} and {@link android.view.MotionEvent#ACTION_UP} events 601 and trigger a special click event. In order to maintain compatibility with accessibility services, 602 the code that handles this custom click event must do the following:</p> 603 604 <ol> 605 <li>Generate an appropriate {@link android.view.accessibility.AccessibilityEvent} for the 606 interpreted click action.</li> 607 <li>Enable accessibility services to perform the custom click action for users who are not able to 608 use a touch screen.</li> 609 </ol> 610 611 <p>To handle these requirements in an efficient way, your code should override the 612 {@link android.view.View#performClick} method, which must call the super implementation of this 613 method and then execute whatever actions are required by the click event. When the custom click 614 action is detected, that code should then call your {@code performClick()} method. The following 615 code example demonstrates this pattern.</p> 616 617 <pre> 618 class CustomTouchView extends View { 619 620 public CustomTouchView(Context context) { 621 super(context); 622 } 623 624 boolean mDownTouch = false; 625 626 @Override 627 public boolean onTouchEvent(MotionEvent event) { 628 super.onTouchEvent(event); 629 630 // Listening for the down and up touch events 631 switch (event.getAction()) { 632 case MotionEvent.ACTION_DOWN: 633 mDownTouch = true; 634 return true; 635 636 case MotionEvent.ACTION_UP: 637 if (mDownTouch) { 638 mDownTouch = false; 639 performClick(); // Call this method to handle the response, and 640 // thereby enable accessibility services to 641 // perform this action for a user who cannot 642 // click the touchscreen. 643 return true; 644 } 645 } 646 return false; // Return false for other touch events 647 } 648 649 @Override 650 public boolean performClick() { 651 // Calls the super implementation, which generates an AccessibilityEvent 652 // and calls the onClick() listener on the view, if any 653 super.performClick(); 654 655 // Handle the action for the custom click here 656 657 return true; 658 } 659 } 660 </pre> 661 662 <p>The pattern shown above makes sure that the custom click event is compatible with 663 accessibility services by using the {@link android.view.View#performClick} method to both generate 664 an accessibility event and provide an entry point for accessibility services to act on behalf of a 665 user to perform this custom click event.</p> 666 667 <p class="note"><strong>Note:</strong> If your custom view has distinct clickable regions, such as 668 a custom calendar view, you must implement a <a href="#virtual-hierarchy">virtual view 669 hierarchy</a> by overriding {@link android.view.View#getAccessibilityNodeProvider} in your custom 670 view in order to be compatible with accessibility services.</p> 671 672 673 <h2 id="test">Testing Accessibility</h2> 674 675 <p>Testing the accessibility of your application is an important part of ensuring your users have a 676 great experience. You can test the most important accessibility features by using your application 677 with audible feedback enabled and navigating within your application using only directional 678 controls. For more information on testing accessibility in your application, see the 679 <a href="{@docRoot}tools/testing/testing_accessibility.html">Accessibility Testing Checklist</a>. 680 </p> 681 682