| page.title=Making Applications Accessible |
| parent.title=Accessibility |
| parent.link=index.html |
| @jd:body |
| |
| <div id="qv-wrapper"> |
| <div id="qv"> |
| |
| <h2>In this document</h2> |
| <ol> |
| <li><a href="#label-ui">Labeling User Interface Elements</a></li> |
| <li><a href="#focus-nav">Enabling Focus Navigation</a> |
| <ol> |
| <li><a href="#focus-enable">Enabling view focus</a></li> |
| <li><a href="#focus-order">Controlling focus order</a></li> |
| </ol> |
| </li> |
| <li><a href="#custom-views">Building Accessible Custom Views</a> |
| <ol> |
| <li><a href="#directional-control">Handling directional controller clicks</a></li> |
| <li><a href="#accessibility-methods">Implementing accessibility API methods</a></li> |
| <li><a href="#send-events">Sending accessibility events</a></li> |
| <li><a href="#populate-events">Populating accessibility events</a></li> |
| <li><a href="#virtual-hierarchy">Providing a customized accessibility context</a></li> |
| <li><a href="#custom-touch-events">Handling custom touch events</a></li> |
| </ol> |
| </li> |
| <li><a href="#test">Testing Accessibility</a></li> |
| </ol> |
| |
| <h2>Key classes</h2> |
| <ol> |
| <li>{@link android.view.accessibility.AccessibilityEvent}</li> |
| <li>{@link android.view.accessibility.AccessibilityNodeInfo}</li> |
| <li>{@link android.support.v4.view.accessibility.AccessibilityNodeInfoCompat}</li> |
| <li>{@link android.view.View.AccessibilityDelegate}</li> |
| <li>{@link android.support.v4.view.AccessibilityDelegateCompat}</li> |
| </ol> |
| |
| <h2>See also</h2> |
| <ol> |
| <li><a href="checklist.html">Accessibility Developer Checklist</a><li> |
| <li><a href="{@docRoot}tools/testing/testing_accessibility.html">Accessibility Testing Checklist</a><li> |
| <li><a href="{@docRoot}design/patterns/accessibility.html">Android Design: Accessibility</a></li> |
| <li><a href="{@docRoot}training/design-navigation/index.html">Designing Effective Navigation</a></li> |
| <li><a href="{@docRoot}training/accessibility/index.html">Training: Implementing Accessibility</a></li> |
| </ol> |
| |
| </div> |
| </div> |
| |
| <p>Applications built for Android are more accessible to users with visual, physical or age-related |
| limitations when those users activate accessibility services and features on a device. These |
| services make your application more accessible even if you do not make any accessibility changes |
| to your code. However, there are steps you should take to optimize the accessibility of your |
| application and ensure a pleasant experience for all your users.</p> |
| |
| <p>Making sure your application is accessible to all users requires only a few steps, particularly |
| when you create your user interface with the components provided by the Android framework. If you |
| use only the standard components for your application, the steps are:</p> |
| |
| <ol> |
| <li>Add descriptive text to user interface controls in your application using the |
| <a href="{@docRoot}reference/android/view/View.html#attr_android:contentDescription"> |
| {@code android:contentDescription}</a> attribute. Pay particular attention to |
| {@link android.widget.ImageButton}, {@link android.widget.ImageView} |
| and {@link android.widget.CheckBox}.</li> |
| <li>Make sure that all user interface elements that can accept input (touches or typing) can be |
| reached with a directional controller, such as a trackball, D-pad (physical or virtual) or |
| navigation <a href="http://support.google.com/android/bin/topic.py?hl=en&topic=2492346">gestures |
| </a>.</li> |
| <li>Make sure that audio prompts are always accompanied by another visual prompt or notification, |
| to assist users who are deaf or hard of hearing.</li> |
| <li>Test your application using only accessibility navigation services and features. Turn on |
| <a href="{@docRoot}tools/testing/testing_accessibility.html#testing-talkback">TalkBack</a> and |
| <a href="{@docRoot}tools/testing/testing_accessibility.html#testing-ebt">Explore by Touch</a>, |
| and then try using your application using only directional controls. For more information on |
| testing for accessibility, see the <a href="{@docRoot}tools/testing/testing_accessibility.html"> |
| Accessibility Testing Checklist</a>.</li> |
| </ol> |
| |
| <p>If you build custom controls that extend the {@link android.view.View} class, you must complete |
| some additional work to make sure your components are accessible. This document discusses how to |
| make custom view controls compatible with accessibility services.</p> |
| |
| <p class="note"> |
| <strong>Note:</strong> The implementation steps in this document describe the requirements for |
| making your application accessible for users with blindness or low-vision. Be sure to review the |
| requirements for serving users who are deaf and hard of hearing in the |
| <a href="{@docRoot}guide/topics/ui/accessibility/checklist.html">Accessibility Developer |
| Checklist</a></p>. |
| |
| |
| |
| <h2 id="label-ui">Labeling User Interface Elements</h2> |
| |
| <p>Many user interface controls depend on visual cues to indicate their meaning and usage. For |
| example, a note-taking application might use an {@link android.widget.ImageButton} with a |
| picture of a plus sign to indicate that the user can add a new note. An {@link |
| android.widget.EditText} component may have a label near it that indicates its purpose. A user |
| with impaired vision can't see these cues well enough to follow them, which makes them useless.</p> |
| |
| <p>You can make these controls more accessible with the |
| <a href="{@docRoot}reference/android/view/View.html#attr_android:contentDescription"> |
| {@code android:contentDescription}</a> XML layout attribute. The text in this attribute does not |
| appear on screen, but if the user enables accessibility services that provide audible prompts, then |
| when the user navigates to that control, the text is spoken.</p> |
| |
| <p>For this reason, set the |
| <a href="{@docRoot}reference/android/view/View.html#attr_android:contentDescription"> |
| {@code android:contentDescription}</a> attribute for every {@link android.widget.ImageButton}, |
| {@link android.widget.ImageView}, {@link android.widget.CheckBox} |
| in your application's user interface, and add descriptions to any other input controls that might |
| require additional information for users who are not able to see it.</p> |
| |
| <p>For example, the following {@link android.widget.ImageButton} sets the content description for |
| the plus button to the {@code add_note} string resource, which could be defined as “Add note" for an |
| English language interface:</p> |
| |
| <pre> |
| <ImageButton |
| android:id=”@+id/add_note_button” |
| android:src=”@drawable/add_note” |
| android:contentDescription=”@string/add_note”/> |
| </pre> |
| |
| <p>By including the description, an accessibility service that provides spoken feedback can announce |
| "Add note" when a user moves focus to this button or hovers over it.</p> |
| |
| <p class="note"><strong>Note:</strong> For {@link android.widget.EditText} fields, provide an |
| <a href="{@docRoot}reference/android/widget/TextView.html#attr_android:hint">android:hint</a> |
| attribute <em>instead</em> of a content description, to help users understand what content is |
| expected when the text field is empty. When the field is filled, TalkBack reads the entered |
| content to the user, instead of the hint text.</p> |
| |
| |
| <h2 id="focus-nav">Enabling Focus Navigation</h2> |
| |
| <p>Focus navigation allows users with disabilities to step through user interface controls using a |
| directional controller. Directional controllers can be physical, such as a trackball, directional |
| pad (D-pad) or arrow keys, or virtual, such as the |
| <a href="https://play.google.com/store/apps/details?id=com.googlecode.eyesfree.inputmethod.latin"> |
| Eyes-Free Keyboard</a>, or the gestures navigation mode available in Android 4.1 and higher. |
| Directional controllers are a primary means of navigation for many Android users. |
| </p> |
| |
| <p>To ensure that users can navigate your application using only a directional controller, verify |
| that all user interface (UI) input controls in your application can be reached and activated |
| without using the touchscreen. You should also verify that clicking with the center button (or OK |
| button) of a directional controller has the same effect as touching a control that already has |
| focus. For information on testing directional controls, see |
| <a href="{@docRoot}tools/testing/testing_accessibility.html#test-navigation">Testing |
| focus navigation</a>.</p> |
| |
| |
| <h3 id="focus-enable">Enabling view focus</h3> |
| |
| <p>A user interface element is reachable using directional controls when its |
| <a href="{@docRoot}reference/android/view/View.html#attr_android:focusable"> |
| {@code android:focusable}</a> attribute is set to {@code true}. This setting allows users to focus |
| on the element using the directional controls and then interact with it. The user interface controls |
| provided by the Android framework are focusable by default and visually indicate focus by changing |
| the control’s appearance.</p> |
| |
| <p>Android provides several APIs that let you control whether a user interface control is focusable |
| and even request that a control be given focus:</p> |
| |
| <ul> |
| <li>{@link android.view.View#setFocusable setFocusable()}</li> |
| <li>{@link android.view.View#isFocusable isFocusable()}</li> |
| <li>{@link android.view.View#requestFocus requestFocus()}</li> |
| </ul> |
| |
| <p>If a view is not focusable by default, you can make it focusable in your layout file by setting |
| the <a href="{@docRoot}reference/android/view/View.html#attr_android:focusable"> |
| {@code android:focusable}</a> attribute to {@code true} or by calling the its {@link |
| android.view.View#setFocusable setFocusable()} method.</p> |
| |
| |
| <h3 id="focus-order">Controlling focus order</h3> |
| |
| <p>When users navigate in any direction using directional controls, focus is passed from one |
| user interface element (view) to another, as determined by the focus order. This order is based on |
| an algorithm that finds the nearest neighbor in a given direction. In rare cases, the algorithm may |
| not match the order that you intended or may not be logical for users. In these situations, you can |
| provide explicit overrides to the ordering using the following XML attributes in your layout file: |
| </p> |
| |
| <dl> |
| <dt><a href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusDown"> |
| {@code android:nextFocusDown}</a></dt> |
| <dd>Defines the next view to receive focus when the user navigates down.</dd> |
| <dt><a href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusLeft"> |
| {@code android:nextFocusLeft}</a></dt> |
| <dd>Defines the next view to receive focus when the user navigates left.</dd> |
| <dt><a href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusRight"> |
| {@code android:nextFocusRight}</a></dt> |
| <dd>Defines the next view to receive focus when the user navigates right.</dd> |
| <dt><a href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusUp"> |
| {@code android:nextFocusUp}</a></dt> |
| <dd>Defines the next view to receive focus when the user navigates up.</dd> |
| </dl> |
| |
| <p>The following example XML layout shows two focusable user interface elements where the |
| <a href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusDown">{@code |
| android:nextFocusDown}</a> and |
| <a href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusUp">{@code |
| android:nextFocusUp}</a> attributes have been explicitly set. The {@link android.widget.TextView} is |
| located to the right of the {@link android.widget.EditText}. However, since these properties have |
| been set, the {@link android.widget.TextView} element can now be reached by pressing the down arrow |
| when focus is on the {@link android.widget.EditText} element:</p> |
| |
| <pre> |
| <LinearLayout android:orientation="horizontal" |
| ... > |
| <EditText android:id="@+id/edit" |
| android:nextFocusDown=”@+id/text” |
| ... /> |
| <TextView android:id="@+id/text" |
| android:focusable=”true” |
| android:text="Hello, I am a focusable TextView" |
| android:nextFocusUp=”@id/edit” |
| ... /> |
| </LinearLayout> |
| </pre> |
| |
| <p>When modifying focus order, be sure that the navigation works as expected in all directions from |
| each user interface control and when navigating in reverse (to get back to where you came from).</p> |
| |
| <p class="note"><strong>Note:</strong> You can modify the focus order of user interface components |
| at runtime, using methods such as {@link android.view.View#setNextFocusDownId setNextFocusDownId()} |
| and {@link android.view.View#setNextFocusRightId setNextFocusRightId()}.</p> |
| |
| |
| <h2 id="custom-views">Building Accessible Custom Views</h2> |
| |
| <p>If your application requires a <a href="{@docRoot}guide/topics/ui/custom-components.html">custom |
| view component</a>, you must do some additional work to ensure that your custom view is accessible. |
| These are the main tasks for ensuring the accessibility of your view:</p> |
| |
| <ul> |
| <li>Handle directional controller clicks</li> |
| <li>Implement accessibility API methods</li> |
| <li>Send {@link android.view.accessibility.AccessibilityEvent} objects specific to your custom |
| view</li> |
| <li>Populate {@link android.view.accessibility.AccessibilityEvent} and {@link |
| android.view.accessibility.AccessibilityNodeInfo} for your view</li> |
| </ul> |
| |
| |
| <h3 id="directional-control">Handling directional controller clicks</h3> |
| |
| <p>On most devices, clicking a view using a directional controller sends a {@link |
| android.view.KeyEvent} with {@link android.view.KeyEvent#KEYCODE_DPAD_CENTER} to the view currently |
| in focus. All standard Android views already handle {@link |
| android.view.KeyEvent#KEYCODE_DPAD_CENTER} appropriately. When building a custom {@link |
| android.view.View} control, make sure this event has the same effect as touching the view on the |
| touchscreen. </p> |
| |
| <p>Your custom control should also treat the {@link android.view.KeyEvent#KEYCODE_ENTER} event the |
| same as {@link android.view.KeyEvent#KEYCODE_DPAD_CENTER}. This approach makes interaction from a |
| full keyboard much easier for users.</p> |
| |
| |
| <h3 id="accessibility-methods">Implementing accessibility API methods</h3> |
| |
| <p>Accessibility events are messages about users interaction with visual interface components in |
| your application. These messages are handled by <a href="services.html">Accessibility Services</a>, |
| which use the information in these events to produce supplemental feedback and prompts. In |
| Android 4.0 (API Level 14) and higher, the methods for |
| generating accessibility events have been expanded to provide more detailed information than the |
| {@link android.view.accessibility.AccessibilityEventSource} interface introduced in Android 1.6 (API |
| Level 4). The expanded accessibility methods are part of the {@link android.view.View} class as well |
| as the {@link android.view.View.AccessibilityDelegate} class. The methods are as follows:</p> |
| |
| <dl> |
| <dt>{@link android.view.View#sendAccessibilityEvent sendAccessibilityEvent()}</dt> |
| <dd>(API Level 4) This method is called when a user takes action on a view. The event is |
| classified with a user action type such as {@link |
| android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED TYPE_VIEW_CLICKED}. You typically do |
| not need to implement this method unless you are creating a custom view.</dd> |
| |
| <dt>{@link android.view.View#sendAccessibilityEventUnchecked |
| sendAccessibilityEventUnchecked()}</dt> |
| <dd>(API Level 4) This method is used when the calling code needs to directly control the check |
| for accessibility being enabled on the device ({@link |
| android.view.accessibility.AccessibilityManager#isEnabled AccessibilityManager.isEnabled()}). If |
| you do implement this method, you must perform the call as if accessibility is enabled, regardless |
| of the actual system setting. You typically do not need to implement this method for a custom view. |
| </dd> |
| |
| <dt>{@link android.view.View#dispatchPopulateAccessibilityEvent |
| dispatchPopulateAccessibilityEvent()}</dt> |
| <dd>(API Level 4) The system calls this method when your custom view generates an |
| accessibility event. As of API Level 14, the default implementation of this method calls {@link |
| android.view.View#onPopulateAccessibilityEvent onPopulateAccessibilityEvent()} for this view and |
| then the {@link android.view.View#dispatchPopulateAccessibilityEvent |
| dispatchPopulateAccessibilityEvent()} method for each child of this view. In order to support |
| accessibility services on revisions of Android <em>prior</em> to 4.0 (API Level 14) you |
| <em>must</em> override this method and populate {@link |
| android.view.accessibility.AccessibilityEvent#getText} with descriptive text for your custom |
| view, which is spoken by accessibility services, such as TalkBack.</dd> |
| |
| <dt>{@link android.view.View#onPopulateAccessibilityEvent onPopulateAccessibilityEvent()}</dt> |
| <dd>(API Level 14) This method sets the spoken text prompt of the {@link |
| android.view.accessibility.AccessibilityEvent} for your view. This method is also called if the |
| view is a child of a view which generates an accessibility event. |
| |
| <p class="note"><strong>Note:</strong> Modifying additional attributes beyond the text within |
| this method potentially overwrites properties set by other methods. While you can modify |
| attributes of the accessibility event with this method, you should limit these changes |
| to text content, and use the {@link android.view.View#onInitializeAccessibilityEvent |
| onInitializeAccessibilityEvent()} method to modify other properties of the event.</p> |
| |
| <p class="note"><strong>Note:</strong> If your implementation of this event completely |
| overrides the output text without allowing other parts of your layout to modify its content, then |
| do not call the super implementation of this method in your code.</p> |
| </dd> |
| |
| <dt>{@link android.view.View#onInitializeAccessibilityEvent onInitializeAccessibilityEvent()}</dt> |
| <dd>(API Level 14) The system calls this method to obtain additional information about the |
| state of the view, beyond text content. If your custom view provides interactive control beyond a |
| simple {@link android.widget.TextView} or {@link android.widget.Button}, you should override this |
| method and set the additional information about your view into the event using this method, such as |
| password field type, checkbox type or states that provide user interaction or feedback. If you |
| do override this method, you must call its super implementation and then only modify properties |
| that have not been set by the super class.</dd> |
| |
| <dt>{@link android.view.View#onInitializeAccessibilityNodeInfo |
| onInitializeAccessibilityNodeInfo()}</dt> |
| <dd>(API Level 14) This method provides accessibility services with information about the state of |
| the view. The default {@link android.view.View} implementation has a standard set of view |
| properties, but if your custom view provides interactive control beyond a simple {@link |
| android.widget.TextView} or {@link android.widget.Button}, you should override this method and set |
| the additional information about your view into the {@link |
| android.view.accessibility.AccessibilityNodeInfo} object handled by this method.</dd> |
| |
| <dt>{@link android.view.ViewGroup#onRequestSendAccessibilityEvent |
| onRequestSendAccessibilityEvent()}</dt> |
| <dd>(API Level 14) The system calls this method when a child of your view has generated an |
| {@link android.view.accessibility.AccessibilityEvent}. This step allows the parent view to amend |
| the accessibility event with additional information. You should implement this method only if your |
| custom view can have child views and if the parent view can provide context information to the |
| accessibility event that would be useful to accessibility services.</dd> |
| </dl> |
| |
| <p>In order to support these accessibility methods for a custom view, you should take one of the |
| following approaches:</p> |
| |
| <ul> |
| <li>If your application targets Android 4.0 (API level 14) and higher, override and implement the |
| accessibility methods listed above directly in your custom view class.</li> |
| <li>If your custom view is intended to be compatible with Android 1.6 (API Level 4) and above, add |
| the Android <a href="{@docRoot}tools/support-library/index.html">Support Library</a>, revision 5 or |
| higher, to your project. Then, within your custom view class, call the |
| {@link android.support.v4.view.ViewCompat#setAccessibilityDelegate |
| ViewCompat.setAccessibilityDelegate()} method to implement the accessibility methods |
| above. For an example of this approach, see the Android Support Library (revision 5 or higher) |
| sample {@code AccessibilityDelegateSupportActivity} in |
| ({@code <sdk>/extras/android/support/v4/samples/Support4Demos/}) |
| </li> |
| </ul> |
| |
| <p>In either case, you should implement the following accessibility methods for your custom view |
| class:</p> |
| |
| <ul> |
| <li>{@link android.view.View#dispatchPopulateAccessibilityEvent |
| dispatchPopulateAccessibilityEvent()}</li> |
| <li>{@link android.view.View#onPopulateAccessibilityEvent |
| onPopulateAccessibilityEvent()}</li> |
| <li>{@link android.view.View#onInitializeAccessibilityEvent |
| onInitializeAccessibilityEvent()}</li> |
| <li>{@link android.view.View#onInitializeAccessibilityNodeInfo |
| onInitializeAccessibilityNodeInfo()}</li> |
| </ul> |
| |
| <p>For more information about implementing these methods, see <a href="#populate-events">Populating |
| Accessibility Events</a>.</p> |
| |
| |
| <h3 id="send-events">Sending accessibility events</h3> |
| |
| <p>Depending on the specifics of your custom view, it may need to send {@link |
| android.view.accessibility.AccessibilityEvent} objects at a different times or for events not |
| handled by the default implementation. The {@link android.view.View} class provides a default |
| implementation for these event types:</p> |
| |
| <ul> |
| <li>Starting with API Level 4: |
| <ul> |
| <li>{@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED}</li> |
| |
| <li>{@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_LONG_CLICKED}</li> |
| |
| <li>{@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_FOCUSED}</li> |
| </ul> |
| </li> |
| <li>Starting with API Level 14: |
| <ul> |
| <li>{@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SCROLLED}</li> |
| |
| <li>{@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}</li> |
| |
| <li>{@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_EXIT}</li> |
| </ul> |
| </li> |
| </ul> |
| |
| <p class="note"><strong>Note:</strong> Hover events are associated with the Explore by |
| Touch feature, which uses these events as triggers for providing audible prompts for user interface |
| elements.</p> |
| |
| <p>In general, you should send an {@link android.view.accessibility.AccessibilityEvent} whenever the |
| content of your custom view changes. For example, if you are implementing a custom slider bar that |
| allows a user to select a numeric value by pressing the left or right arrows, your custom view |
| should emit an event of type {@link |
| android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED} whenever the slider |
| value changes. The following sample code demonstrates the use of the {@link |
| android.view.accessibility.AccessibilityEventSource#sendAccessibilityEvent |
| sendAccessibilityEvent()} method to report this event.</p> |
| |
| <pre> |
| @Override |
| public boolean onKeyUp (int keyCode, KeyEvent event) { |
| if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) { |
| mCurrentValue--; |
| sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED); |
| return true; |
| } |
| ... |
| } |
| </pre> |
| |
| |
| <h3 id="populate-events">Populating accessibility events</h3> |
| |
| <p>Each {@link android.view.accessibility.AccessibilityEvent} has a set of required properties that |
| describe the current state of the view. These properties include things such as the view’s class |
| name, content description and checked state. The specific properties required for each event type |
| are described in the {@link android.view.accessibility.AccessibilityEvent} reference documentation. |
| The {@link android.view.View} implementation provides default values for these properties. Many of |
| these values, including the class name and event timestamp, are provided automatically. If you are |
| creating a custom view component, you must provide some information about the content and |
| characteristics of the view. This information may be as simple as a button label, but may also |
| include additional state information that you want to add to the event.</p> |
| |
| <p>The minimum requirement for providing information to accessibility services with a custom |
| view is to implement {@link android.view.View#dispatchPopulateAccessibilityEvent |
| dispatchPopulateAccessibilityEvent()}. This method is called by the system to request |
| information for an {@link android.view.accessibility.AccessibilityEvent} and makes your custom |
| view compatible with accessibility services on Android 1.6 (API Level 4) and higher. The |
| following example code demonstrates a basic implementation of this method.</p> |
| |
| <pre> |
| @Override |
| public void dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { |
| super.dispatchPopulateAccessibilityEvent(event); |
| // Call the super implementation to populate its text to the event, which |
| // calls onPopulateAccessibilityEvent() on API Level 14 and up. |
| |
| // In case this is running on a API revision earlier that 14, check |
| // the text content of the event and add an appropriate text |
| // description for this custom view: |
| CharSequence text = getText(); |
| if (!TextUtils.isEmpty(text)) { |
| event.getText().add(text); |
| } |
| } |
| </pre> |
| |
| <p>For Android 4.0 (API Level 14) and higher, use the {@link |
| android.view.View#onPopulateAccessibilityEvent onPopulateAccessibilityEvent()} and |
| {@link android.view.View#onInitializeAccessibilityEvent onInitializeAccessibilityEvent()} |
| methods to populate or modify the information in an {@link |
| android.view.accessibility.AccessibilityEvent}. Use the |
| {@link android.view.View#onPopulateAccessibilityEvent onPopulateAccessibilityEvent()} method |
| specifically for adding or modifying the text content of the event, which is turned into audible |
| prompts by accessibility services such as TalkBack. Use the |
| {@link android.view.View#onInitializeAccessibilityEvent onInitializeAccessibilityEvent()} method for |
| populating additional information about the event, such as the selection state of the view.</p> |
| |
| <p>In addition, implement the |
| {@link android.view.View#onInitializeAccessibilityNodeInfo onInitializeAccessibilityNodeInfo()} |
| method. The {@link android.view.accessibility.AccessibilityNodeInfo} objects populated by this method |
| are used by accessibility services to investigate the view hierarchy that generated an accessibility |
| event after receiving that event, to obtain a more detailed context information and provide |
| appropriate feedback to users.</p> |
| |
| <p>The example code below shows how override these three methods by using |
| {@link android.support.v4.view.ViewCompat#setAccessibilityDelegate |
| ViewCompat.setAccessibilityDelegate()}. Note that this sample code requires that the Android |
| <a href="{@docRoot}tools/support-library/index.html">Support Library</a> for API Level 4 (revision |
| 5 or higher) is added to your project.</p> |
| |
| <pre> |
| ViewCompat.setAccessibilityDelegate(new AccessibilityDelegateCompat() { |
| @Override |
| public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) { |
| super.onPopulateAccessibilityEvent(host, event); |
| // We call the super implementation to populate its text for the |
| // event. Then we add our text not present in a super class. |
| // Very often you only need to add the text for the custom view. |
| CharSequence text = getText(); |
| if (!TextUtils.isEmpty(text)) { |
| event.getText().add(text); |
| } |
| } |
| @Override |
| public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { |
| super.onInitializeAccessibilityEvent(host, event); |
| // We call the super implementation to let super classes |
| // set appropriate event properties. Then we add the new property |
| // (checked) which is not supported by a super class. |
| event.setChecked(isChecked()); |
| } |
| @Override |
| public void onInitializeAccessibilityNodeInfo(View host, |
| AccessibilityNodeInfoCompat info) { |
| super.onInitializeAccessibilityNodeInfo(host, info); |
| // We call the super implementation to let super classes set |
| // appropriate info properties. Then we add our properties |
| // (checkable and checked) which are not supported by a super class. |
| info.setCheckable(true); |
| info.setChecked(isChecked()); |
| // Quite often you only need to add the text for the custom view. |
| CharSequence text = getText(); |
| if (!TextUtils.isEmpty(text)) { |
| info.setText(text); |
| } |
| } |
| } |
| </pre> |
| |
| <p>In applications targeting Android 4.0 (API Level 14) and higher, you can implement these methods |
| directly in your custom view class. For another example of this approach, see the Android |
| <a href="{@docRoot}tools/support-library/index.html">Support Library</a> (revision 5 or higher) |
| sample {@code AccessibilityDelegateSupportActivity} in |
| ({@code <sdk>/extras/android/support/v4/samples/Support4Demos/}).</p> |
| |
| <p class="note"><strong>Note:</strong> You may find information on implementing accessibility for |
| custom views written prior to Android 4.0 that describes the use of the |
| {@link android.view.View#dispatchPopulateAccessibilityEvent dispatchPopulateAccessibilityEvent()} |
| method for populating AccessibilityEvents. As of the Android 4.0 release, however, the recommended |
| approach is to use the |
| {@link android.view.View#onPopulateAccessibilityEvent onPopulateAccessibilityEvent()} and |
| {@link android.view.View#onInitializeAccessibilityEvent onInitializeAccessibilityEvent()} |
| methods.</p> |
| |
| |
| <h3 id="virtual-hierarchy">Providing a customized accessibility context</h3> |
| |
| <p>In Android 4.0 (API Level 14), the framework was enhanced to allow accessibility services to |
| inspect the containing view hierarchy of a user interface component that generates an |
| accessibility event. This enhancement allows accessibility services to provide a much richer set |
| of contextual information with which to aid users.</p> |
| |
| <p>There are some cases where accessibility services cannot get adequate information |
| from the view hierarchy. An example of this is a custom interface control that has two or more |
| separately clickable areas, such as a calendar control. In this case, the services cannot get |
| adequate information because the clickable subsections are not part of the view hierarchy.</p> |
| |
| <img src="calendar.png" alt="" id="figure1" /> |
| <p class="img-caption"> |
| <strong>Figure 1.</strong> A custom calendar view with selectable day elements. |
| </p> |
| |
| <p>In the example shown in Figure 1, the entire calendar is implemented as a single view, so if you |
| do not do anything else, accessibility services do not receive enough information about the |
| content of the view and the user's selection within the view. For example, if a user clicks on the |
| day containing <strong>17</strong>, the accessibility framework only receives the description |
| information for the whole calendar control. In this case, the TalkBack accessibility service would |
| simply announce "Calendar" or, only slightly better, "April Calendar" and the user would be left |
| to wonder what day was selected.</p> |
| |
| <p>To provide adequate context information for accessibility services in situations like this, |
| the framework provides a way to specify a virtual view hierarchy. A <em>virtual view |
| hierarchy</em> is a way for application developers to provide a complementary view hierarchy |
| to accessibility services that more closely matches the actual information on screen. This |
| approach allows accessibility services to provide more useful context information to users.</p> |
| |
| <p>Another situation where a virtual view hierarchy may be needed is a user interface containing |
| a set of controls (views) that have closely related functions, where an action on one control |
| affects the contents of one or more elements, such as a number picker with separate up and down |
| buttons. In this case, accessibility services cannot get adequate information because action on |
| one control changes content in another and the relationship of those controls may not be apparent |
| to the service. To handle this situation, group the related controls with a containing view and |
| provide a virtual view hierarchy from this container to clearly represent the information and |
| behavior provided by the controls.</p> |
| |
| <p>In order to provide a virtual view hierarchy for a view, override the {@link |
| android.view.View#getAccessibilityNodeProvider} method in your custom view or view group and |
| return an implementation of {@link android.view.accessibility.AccessibilityNodeProvider}. For an |
| example implementation of this accessibility feature, see |
| {@code AccessibilityNodeProviderActivity} in the ApiDemos sample project. You can implement a |
| virtual view hierarchy that is compatible with Android 1.6 and later by using the |
| <a href="{@docRoot}tools/support-library/index.html">Support Library</a> with the |
| {@link android.support.v4.view.ViewCompat#getAccessibilityNodeProvider |
| ViewCompat.getAccessibilityNodeProvider()} method and providing an implementation with |
| {@link android.support.v4.view.accessibility.AccessibilityNodeProviderCompat}.</p> |
| |
| |
| <h3 id="custom-touch-events">Handling custom touch events</h3> |
| |
| <p>Custom view controls may require non-standard touch event behavior. For example, a custom |
| control may use the {@link android.view.View#onTouchEvent} listener method to detect the |
| {@link android.view.MotionEvent#ACTION_DOWN} and {@link android.view.MotionEvent#ACTION_UP} events |
| and trigger a special click event. In order to maintain compatibility with accessibility services, |
| the code that handles this custom click event must do the following:</p> |
| |
| <ol> |
| <li>Generate an appropriate {@link android.view.accessibility.AccessibilityEvent} for the |
| interpreted click action.</li> |
| <li>Enable accessibility services to perform the custom click action for users who are not able to |
| use a touch screen.</li> |
| </ol> |
| |
| <p>To handle these requirements in an efficient way, your code should override the |
| {@link android.view.View#performClick} method, which must call the super implementation of this |
| method and then execute whatever actions are required by the click event. When the custom click |
| action is detected, that code should then call your {@code performClick()} method. The following |
| code example demonstrates this pattern.</p> |
| |
| <pre> |
| class CustomTouchView extends View { |
| |
| public CustomTouchView(Context context) { |
| super(context); |
| } |
| |
| boolean mDownTouch = false; |
| |
| @Override |
| public boolean onTouchEvent(MotionEvent event) { |
| super.onTouchEvent(event); |
| |
| // Listening for the down and up touch events |
| switch (event.getAction()) { |
| case MotionEvent.ACTION_DOWN: |
| mDownTouch = true; |
| return true; |
| |
| case MotionEvent.ACTION_UP: |
| if (mDownTouch) { |
| mDownTouch = false; |
| performClick(); // Call this method to handle the response, and |
| // thereby enable accessibility services to |
| // perform this action for a user who cannot |
| // click the touchscreen. |
| return true; |
| } |
| } |
| return false; // Return false for other touch events |
| } |
| |
| @Override |
| public boolean performClick() { |
| // Calls the super implementation, which generates an AccessibilityEvent |
| // and calls the onClick() listener on the view, if any |
| super.performClick(); |
| |
| // Handle the action for the custom click here |
| |
| return true; |
| } |
| } |
| </pre> |
| |
| <p>The pattern shown above makes sure that the custom click event is compatible with |
| accessibility services by using the {@link android.view.View#performClick} method to both generate |
| an accessibility event and provide an entry point for accessibility services to act on behalf of a |
| user to perform this custom click event.</p> |
| |
| <p class="note"><strong>Note:</strong> If your custom view has distinct clickable regions, such as |
| a custom calendar view, you must implement a <a href="#virtual-hierarchy">virtual view |
| hierarchy</a> by overriding {@link android.view.View#getAccessibilityNodeProvider} in your custom |
| view in order to be compatible with accessibility services.</p> |
| |
| |
| <h2 id="test">Testing Accessibility</h2> |
| |
| <p>Testing the accessibility of your application is an important part of ensuring your users have a |
| great experience. You can test the most important accessibility features by using your application |
| with audible feedback enabled and navigating within your application using only directional |
| controls. For more information on testing accessibility in your application, see the |
| <a href="{@docRoot}tools/testing/testing_accessibility.html">Accessibility Testing Checklist</a>. |
| </p> |
| |