Making Applications Accessible

Making Applications Accessible

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.

这里有一些服务可以使你的app更加容易被使用,即使你没有在你的代码里面采取任何相关的措施。但是,你必须按以下步骤组织你app的易获得性,并且保证你的用户有一次愉快的体验。

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:

保证你的app对所有用户都易使用,只需要几个步骤。尤其当你使用android通过的组件接口。如果你只使用标准的组件,步骤如下:

  1. Add descriptive text to user interface controls in your application using the android:contentDescription attribute. Pay particular attention to ImageButtonImageView and CheckBox.                               给你的控件,使用android:contentDescription增加描述性的文字。尤其是ImageButtonImageView and CheckBox
  2. 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 navigationgestures .                                             保证所有可以输入的接口元素,都可以通过方向控制器控制,例如跟踪球,方向键,手势导航。
  3. Make sure that audio prompts are always accompanied by another visual prompt or notification, to assist users who are deaf or hard of hearing.                   保证你的声音提示,总是伴随其他看见的提示出现,帮助那些听力有缺陷的用户。
  4. Test your application using only accessibility navigation services and features. Turn on TalkBack and Explore by Touch, and then try using your application using only directional controls. For more information on testing for accessibility, see the Accessibility Testing Checklist.                                   只使用易使用的导航设备和特性去测试你app。打开TalkBackExplore by Touch,然后尝试只使用方向控制去使用你的app。更多信息,请看Accessibility Testing Checklist.

If you build custom controls that extend the 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.

如果你通过继承View来创建控件。你必须做一些额外的工作来保证易使用性。这篇文章讨论关于怎么使一般的控件和易使用性服务结合。

Note: 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 Accessibility Developer Checklist

文章描述了使你app对盲人或者视力低下的用户更加容易使用的一些必须步骤。记得复习一下Accessibility Developer Checklist

.

Labeling User Interface Elements


Many user interface controls depend on visual cues to indicate their meaning and usage. For example, a note-taking application might use an ImageButton with a picture of a plus sign to indicate that the user can add a new note. An 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.

许多用户接口依赖于视觉来告诉用户它们的用意和使用方式。例如,一个文字转声音的app可能使用一个带有按下标志的ImageButton,去提醒用户可以新增文本。一个EditText附近可能有一个的图标去告诉别人的用处。视觉受损的用户不能看清这些线索,导致它们没有发挥作用。

You can make these controls more accessible with the android:contentDescription 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.

你可以通过在xml里面设置android:contentDescription使这些控件容易被使用。这些文字不会出现在屏幕,但是如果用户开启了提供声音提示的易获得性服务,当它们使用控件时,文本会被读出来。

For this reason, set the android:contentDescription attribute for every ImageButtonImageView,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.

因此,在app里面为每个ImageButtonImageView,CheckBox设置android:contentDescription设置属性,并且为所有需要提示的输入控件增加描述文字,可以帮到那些看不见它的用户。

For example, the following ImageButton sets the content description for the plus button to the add_note string resource, which could be defined as “Add note" for an English language interface:

例如:下面的ImageButton设置了内容描述

<ImageButton
    android:id=”@+id/add_note_button”
    android:src=”@drawable/add_note”
    android:contentDescription=”@string/add_note”/>

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.

通过包含描述,当用户focuse或者hover这个按钮的时候,易获得服务会提供声音回调朗读出“Add note”文字

Note: For EditText fields, provide an android:hint attribute instead 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.

对于EditText,提供android:hint来代替content description,去帮助用户明白我们希望他们在空白域填写什么内容。当域被填写了,语音来读取输入的内容,而不是hint文本。

Enabling Focus Navigation


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 Eyes-Free Keyboard, or the gestures navigation mode available in Android 4.1 and higher. Directional controllers are a primary means of navigation for many Android users.

聚焦导航使残疾用户可以通过方向控制使用控件。方向控制可以使身体上的,例如轨迹球,方向键,视觉上的,例如Eyes-Free Keyboard或者在4.1以上版本的手势导航。方向控制是需要Android用户的主要使用方式。

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 Testing focus navigation.

保证用户只使用方向控制就可以控制你的app,验证你所有的UI都可以不需要触碰屏幕就可以到达和激活。你同时需要保证点击方向控制的中心按钮和触摸那些已经被focus的控件有一样的效果。

Enabling view focus

A user interface element is reachable using directional controls when its android:focusable attribute is set totrue. 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.

当一个控件的focusable属性被设置为true,控件就是可以通过方向控制可达的。这个设置让用户专注于使用方向控制的元素,并且和它交互。Android通过的交互控件默认就是focusable,并且通过控件外表来可视地告诉用户它处于focus状态。

Android provides several APIs that let you control whether a user interface control is focusable and even request that a control be given focus:

Android通过了几个和focusable相关的API

If a view is not focusable by default, you can make it focusable in your layout file by setting theandroid:focusable attribute to true or by calling the its setFocusable() method.

如果控件默认不能focus,你可以通过在布局文件设置android:focusable,或者调用setFocusable()方法

Controlling focus order

控制focus顺序

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:

当用户使用方向控制时,focus按照顺序从一个View传递到下一个。顺序是根据查找最近相邻元素的算法实现的。在少见的情况下,算法匹配的顺序可能和用户想的不一样。在这种情况下,你需要通过在layout文件栏目设置xml属性。

android:nextFocusDown
Defines the next view to receive focus when the user navigates down.
设置按下down后的下一个收到focus的View
android:nextFocusLeft
Defines the next view to receive focus when the user navigates left.
android:nextFocusRight
Defines the next view to receive focus when the user navigates right.
android:nextFocusUp
Defines the next view to receive focus when the user navigates up.

The following example XML layout shows two focusable user interface elements where theandroid:nextFocusDown and android:nextFocusUp attributes have been explicitly set. The TextView is located to the right of the EditText. However, since these properties have been set, the TextView element can now be reached by pressing the down arrow when focus is on the EditText element:

下面的例子展示了设置了android:nextFocusDown 和 android:nextFocusUp两个属性的控件。TextView在EditText的右边。但是由于这些属性被设置,当focus在EditText的时候,TextView可以通过按下down方向键被触及。

<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>

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).

改变这些顺序以后,保证咋所以方向上都可以正常,并且可以返回你原来的位置。

Note: You can modify the focus order of user interface components at runtime, using methods such assetNextFocusDownId() and setNextFocusRightId().

运行时你可使用assetNextFocusDownId() and setNextFocusRightId().来改变focus顺序。

Building Accessible Custom Views


If your application requires a custom view component, 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:

Handling directional controller clicks

On most devices, clicking a view using a directional controller sends a KeyEvent with KEYCODE_DPAD_CENTER to the view currently in focus. All standard Android views already handle KEYCODE_DPAD_CENTER appropriately. When building a custom View control, make sure this event has the same effect as touching the view on the touchscreen.

Your custom control should also treat the KEYCODE_ENTER event the same as KEYCODE_DPAD_CENTER. This approach makes interaction from a full keyboard much easier for users.

Implementing accessibility API methods

Accessibility events are messages about users interaction with visual interface components in your application. These messages are handled by Accessibility Services, 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 theAccessibilityEventSource interface introduced in Android 1.6 (API Level 4). The expanded accessibility methods are part of the View class as well as the View.AccessibilityDelegate class. The methods are as follows:

sendAccessibilityEvent()
(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  TYPE_VIEW_CLICKED. You typically do not need to implement this method unless you are creating a custom view.
sendAccessibilityEventUnchecked()
(API Level 4) This method is used when the calling code needs to directly control the check for accessibility being enabled on the device ( 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.
dispatchPopulateAccessibilityEvent()
(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  onPopulateAccessibilityEvent() for this view and then the  dispatchPopulateAccessibilityEvent() method for each child of this view. In order to support accessibility services on revisions of Android  prior to 4.0 (API Level 14) you  must override this method and populate  getText() with descriptive text for your custom view, which is spoken by accessibility services, such as TalkBack.
onPopulateAccessibilityEvent()
(API Level 14) This method sets the spoken text prompt of the  AccessibilityEvent for your view. This method is also called if the view is a child of a view which generates an accessibility event.

Note: 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 theonInitializeAccessibilityEvent() method to modify other properties of the event.

Note: 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.

onInitializeAccessibilityEvent()
(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  TextView or 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.
onInitializeAccessibilityNodeInfo()
(API Level 14) This method provides accessibility services with information about the state of the view. The default  View implementation has a standard set of view properties, but if your custom view provides interactive control beyond a simple  TextView or  Button, you should override this method and set the additional information about your view into the  AccessibilityNodeInfo object handled by this method.
onRequestSendAccessibilityEvent()
(API Level 14) The system calls this method when a child of your view has generated an 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.

In order to support these accessibility methods for a custom view, you should take one of the following approaches:

  • 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.
  • If your custom view is intended to be compatible with Android 1.6 (API Level 4) and above, add the AndroidSupport Library, revision 5 or higher, to your project. Then, within your custom view class, call theViewCompat.setAccessibilityDelegate() method to implement the accessibility methods above. For an example of this approach, see the Android Support Library (revision 5 or higher) sampleAccessibilityDelegateSupportActivity in (<sdk>/extras/android/support/v4/samples/Support4Demos/)

In either case, you should implement the following accessibility methods for your custom view class:

For more information about implementing these methods, see Populating Accessibility Events.

Sending accessibility events

Depending on the specifics of your custom view, it may need to send AccessibilityEvent objects at a different times or for events not handled by the default implementation. The View class provides a default implementation for these event types:

Note: Hover events are associated with the Explore by Touch feature, which uses these events as triggers for providing audible prompts for user interface elements.

In general, you should send an 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 TYPE_VIEW_TEXT_CHANGED whenever the slider value changes. The following sample code demonstrates the use of the sendAccessibilityEvent()method to report this event.

@Override
public boolean onKeyUp (int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
        mCurrentValue--;
        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
        return true;
    }
    ...
}

Populating accessibility events

Each 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 AccessibilityEvent reference documentation. TheView 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.

The minimum requirement for providing information to accessibility services with a custom view is to implementdispatchPopulateAccessibilityEvent(). This method is called by the system to request information for anAccessibilityEvent 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.

@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);
    }
}

For Android 4.0 (API Level 14) and higher, use the onPopulateAccessibilityEvent() andonInitializeAccessibilityEvent() methods to populate or modify the information in anAccessibilityEvent. Use the 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 onInitializeAccessibilityEvent() method for populating additional information about the event, such as the selection state of the view.

In addition, implement the onInitializeAccessibilityNodeInfo() method. The AccessibilityNodeInfoobjects 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.

The example code below shows how override these three methods by usingViewCompat.setAccessibilityDelegate(). Note that this sample code requires that the Android Support Library for API Level 4 (revision 5 or higher) is added to your project.

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);
        }
    }
}

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 Support Library (revision 5 or higher) sample AccessibilityDelegateSupportActivity in (<sdk>/extras/android/support/v4/samples/Support4Demos/).

Note: You may find information on implementing accessibility for custom views written prior to Android 4.0 that describes the use of the dispatchPopulateAccessibilityEvent() method for populating AccessibilityEvents. As of the Android 4.0 release, however, the recommended approach is to use theonPopulateAccessibilityEvent() and onInitializeAccessibilityEvent() methods.

Providing a customized accessibility context

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.

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.

Figure 1. A custom calendar view with selectable day elements.

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 17, 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.

To provide adequate context information for accessibility services in situations like this, the framework provides a way to specify a virtual view hierarchy. A virtual view hierarchy 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.

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.

In order to provide a virtual view hierarchy for a view, override the getAccessibilityNodeProvider() method in your custom view or view group and return an implementation of AccessibilityNodeProvider. For an example implementation of this accessibility feature, see 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 Support Library with the ViewCompat.getAccessibilityNodeProvider() method and providing an implementation with AccessibilityNodeProviderCompat.

Handling custom touch events

Custom view controls may require non-standard touch event behavior. For example, a custom control may use the onTouchEvent(MotionEvent) listener method to detect the ACTION_DOWN and 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:

  1. Generate an appropriate AccessibilityEvent for the interpreted click action.
  2. Enable accessibility services to perform the custom click action for users who are not able to use a touch screen.

To handle these requirements in an efficient way, your code should override the 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 performClick() method. The following code example demonstrates this pattern.

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;
    }
}

The pattern shown above makes sure that the custom click event is compatible with accessibility services by using the 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.

Note: If your custom view has distinct clickable regions, such as a custom calendar view, you must implement a virtual view hierarchy by overriding getAccessibilityNodeProvider() in your custom view in order to be compatible with accessibility services.

Testing Accessibility


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 Accessibility Testing Checklist.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值