Alexander Lucas | df6c827 | 2012-03-06 18:13:07 -0800 | [diff] [blame] | 1 | |
| 2 | page.title=Developing Accessible Applications |
| 3 | parent.title=Implementing Accessibility |
| 4 | parent.link=index.html |
| 5 | |
| 6 | trainingnavtop=true |
| 7 | next.title=Developing an Accessibility Service |
| 8 | next.link=service.html |
| 9 | |
| 10 | @jd:body |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | <div id="tb-wrapper"> |
| 16 | <div id="tb"> |
| 17 | |
| 18 | <h2>This lesson teaches you to</h2> |
| 19 | <ol> |
| 20 | <li><a href="#contentdesc">Add Content Descriptions</a></li> |
| 21 | <li><a href="#focus">Design for Focus Navigation</a></li> |
| 22 | <li><a href="#events">Fire Accessibility Events</a></li> |
| 23 | <li><a href="#testing">Test Your Application</a></li> |
| 24 | </ol> |
| 25 | |
| 26 | <!-- other docs (NOT javadocs) --> |
| 27 | <h2>You should also read</h2> |
| 28 | <ul> |
| 29 | <li><a href="{@docRoot}guide/topics/ui/accessibility/apps.html">Making |
| 30 | Applications Accessible</a></li> |
| 31 | </ul> |
| 32 | |
| 33 | |
| 34 | </div> |
| 35 | </div> |
| 36 | |
| 37 | <p>Android has several accessibility-focused features baked into the platform, |
| 38 | which make it easy to optimize your application for those with visual or |
| 39 | physical disabilities. However, it's not always obvious what the correct |
| 40 | optimizations are, or the easiest way to leverage the framework toward this |
| 41 | purpose. This lesson shows you how to implement the strategies and platform |
| 42 | features that make for a great accessibility-enabled Android application.</p> |
| 43 | |
| 44 | <h2 id="contentdesc">Add Content Descriptions</h2> |
| 45 | <p>A well-designed user interface (UI) often has elements that don't require an explicit |
| 46 | label to indicate their purpose to the user. A checkbox next to an item in a |
| 47 | task list application has a fairly obvious purpose, as does a trash can in a file |
| 48 | manager application. However, to your users with vision impairment, other UI |
| 49 | cues are needed.</p> |
| 50 | |
| 51 | <p>Fortunately, it's easy to add labels to UI elements in your application that |
| 52 | can be read out loud to your user by a speech-based accessibility service like <a |
Scott Main | f90f4ed | 2012-04-20 11:53:32 -0700 | [diff] [blame] | 53 | href="https://play.google.com/store/apps/details?id=com.google.android.marvin.talkback">TalkBack</a> |
| 54 | . |
Alexander Lucas | df6c827 | 2012-03-06 18:13:07 -0800 | [diff] [blame] | 55 | If you have a label that's likely not to change during the lifecycle of the |
| 56 | application (such as "Pause" or "Purchase"), you can add it via the XML layout, |
| 57 | by setting a UI element's <a |
Scott Main | f90f4ed | 2012-04-20 11:53:32 -0700 | [diff] [blame] | 58 | |
| 59 | href="{@docRoot}reference/android/view/View.html#attr_android:contentDescription" |
| 60 | >{@code android:contentDescription}</a> attribute, like in this |
Alexander Lucas | df6c827 | 2012-03-06 18:13:07 -0800 | [diff] [blame] | 61 | example:</p> |
| 62 | <pre> |
| 63 | <Button |
| 64 | android:id=”@+id/pause_button” |
| 65 | android:src=”@drawable/pause” |
| 66 | android:contentDescription=”@string/pause”/> |
| 67 | </pre> |
| 68 | |
| 69 | <p>However, there are plenty of situations where it's desirable to base the content |
| 70 | description on some context, such as the state of a toggle button, or a piece |
| 71 | selectable data like a list item. To edit the content description at runtime, |
| 72 | use the {@link android.view.View#setContentDescription(CharSequence) |
| 73 | setContentDescription()} method, like this:</p> |
| 74 | |
| 75 | <pre> |
| 76 | String contentDescription = "Select " + strValues[position]; |
| 77 | label.setContentDescription(contentDescription); |
| 78 | </pre> |
| 79 | |
| 80 | <p>This addition to your code is the simplest accessibility improvement you can make to your |
| 81 | application, but one of the most useful. Try to add content descriptions |
| 82 | wherever there's useful information, but avoid the web-developer pitfall of |
| 83 | labelling <em>everything</em> with useless information. For instance, don't set |
| 84 | an application icon's content description to "app icon". That just increases |
| 85 | the noise a user needs to navigate in order to pull useful information from your |
| 86 | interface.</p> |
| 87 | |
| 88 | <p>Try it out! Download <a |
Scott Main | f90f4ed | 2012-04-20 11:53:32 -0700 | [diff] [blame] | 89 | href="https://play.google.com/store/apps/details?id=com.google.android.marvin.talkback">TalkBack</a> |
Alexander Lucas | df6c827 | 2012-03-06 18:13:07 -0800 | [diff] [blame] | 90 | (an accessibility service published by Google) and enable it in <strong>Settings |
| 91 | > Accessibility > TalkBack</strong>. Then navigate around your own |
| 92 | application and listen for the audible cues provided by TalkBack.</p> |
| 93 | |
| 94 | <h2 id="focus">Design for Focus Navigation</h2> |
| 95 | <p>Your application should support more methods of navigation than the |
| 96 | touch screen alone. Many Android devices come with navigation hardware other |
| 97 | than the touchscreen, like a D-Pad, arrow keys, or a trackball. In addition, |
| 98 | later Android releases also support connecting external devices like keyboards |
| 99 | via USB or bluetooth.</p> |
| 100 | |
| 101 | <p>In order to enable this form of navigation, all navigational elements that |
| 102 | the user should be able to navigate to need to be set as focusable. This |
| 103 | modification can be |
| 104 | done at runtime using the |
| 105 | {@link android.view.View#setFocusable View.setFocusable()} method on that UI |
| 106 | control, or by setting the <a |
Scott Main | f90f4ed | 2012-04-20 11:53:32 -0700 | [diff] [blame] | 107 | href="{@docRoot}reference/android/view/View.html#attr_android:focusable">{@code |
Alexander Lucas | df6c827 | 2012-03-06 18:13:07 -0800 | [diff] [blame] | 108 | android:focusable}</a> |
| 109 | attrubute in your XML layout files.</p> |
| 110 | |
| 111 | <p>Also, each UI control has 4 attributes, |
Scott Main | f90f4ed | 2012-04-20 11:53:32 -0700 | [diff] [blame] | 112 | <a href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusUp">{@code |
Alexander Lucas | df6c827 | 2012-03-06 18:13:07 -0800 | [diff] [blame] | 113 | android:nextFocusUp}</a>, |
| 114 | <a |
Scott Main | f90f4ed | 2012-04-20 11:53:32 -0700 | [diff] [blame] | 115 | href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusDown">{@code |
Alexander Lucas | df6c827 | 2012-03-06 18:13:07 -0800 | [diff] [blame] | 116 | android:nextFocusDown}</a>, |
| 117 | <a |
Scott Main | f90f4ed | 2012-04-20 11:53:32 -0700 | [diff] [blame] | 118 | href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusLeft">{@code |
Alexander Lucas | df6c827 | 2012-03-06 18:13:07 -0800 | [diff] [blame] | 119 | android:nextFocusLeft}</a>, |
| 120 | and <a |
Scott Main | f90f4ed | 2012-04-20 11:53:32 -0700 | [diff] [blame] | 121 | href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusRight">{@code |
Alexander Lucas | df6c827 | 2012-03-06 18:13:07 -0800 | [diff] [blame] | 122 | android:nextFocusRight}</a>, |
| 123 | which you can use to designate |
| 124 | the next view to receive focus when the user navigates in that direction. While |
| 125 | the platform determines navigation sequences automatically based on layout |
| 126 | proximity, you can use these attributes to override that sequence if it isn't |
| 127 | appropriate in your application. </p> |
| 128 | |
| 129 | <p>For instance, here's how you represent a button and label, both |
| 130 | focusable, such that pressing down takes you from the button to the text view, and |
| 131 | pressing up would take you back to the button.</p> |
| 132 | |
| 133 | |
| 134 | <pre> |
| 135 | <Button android:id="@+id/doSomething" |
| 136 | android:focusable="true" |
| 137 | android:nextFocusDown=”@id/label” |
| 138 | ... /> |
| 139 | <TextView android:id="@+id/label" |
| 140 | android:focusable=”true” |
| 141 | android:text="@string/labelText" |
| 142 | android:nextFocusUp=”@id/doSomething” |
| 143 | ... /> |
| 144 | </pre> |
| 145 | |
| 146 | <p>Verify that your application works intuitively in these situations. The |
| 147 | easiest way is to simply run your application in the Android emulator, and |
| 148 | navigate around the UI with the emulator's arrow keys, using the OK button as a |
| 149 | replacement for touch to select UI controls.</p> |
| 150 | |
| 151 | <h2 id="events">Fire Accessibility Events</h2> |
| 152 | <p>If you're using the view components in the Android framework, an |
| 153 | {@link android.view.accessibility.AccessibilityEvent} is created whenever you |
| 154 | select an item or change focus in your UI. These events are examined by the |
| 155 | accessibility service, enabling it to provide features like text-to-speech to |
| 156 | the user.</p> |
| 157 | |
| 158 | <p>If you write a custom view, make sure it fires events at the appropriate |
| 159 | times. Generate events by calling {@link |
| 160 | android.view.View#sendAccessibilityEvent(int)}, with a parameter representing |
| 161 | the type of event that occurred. A complete list of the event types currently |
| 162 | supported can be found in the {@link |
| 163 | android.view.accessibility.AccessibilityEvent} reference documentation. |
| 164 | |
| 165 | <p>As an example, if you want to extend an image view such that you can write |
| 166 | captions by typing on the keyboard when it has focus, it makes sense to fire an |
| 167 | {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED} |
| 168 | event, even though that's not normally built into image views. The code to |
| 169 | generate that event would look like this:</p> |
| 170 | <pre> |
| 171 | public void onTextChanged(String before, String after) { |
| 172 | ... |
| 173 | if (AccessibilityManager.getInstance(mContext).isEnabled()) { |
| 174 | sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED); |
| 175 | } |
| 176 | ... |
| 177 | } |
| 178 | </pre> |
| 179 | |
| 180 | <h2 id="testing">Test Your Application</h2> |
| 181 | <p>Be sure to test the accessibility functionality as you add it to your |
| 182 | application. In order to test the content descriptions and Accessibility |
| 183 | events, install and enable an accessibility service. One option is <a |
Scott Main | f90f4ed | 2012-04-20 11:53:32 -0700 | [diff] [blame] | 184 | href="https://play.google.com/store/apps/details?id=com.google.android.marvin.talkback">Talkback</a> |
| 185 | , |
Alexander Lucas | df6c827 | 2012-03-06 18:13:07 -0800 | [diff] [blame] | 186 | a free, open source screen reader available on Google Play. With the service |
| 187 | enabled, test all the navigation flows through your application and listen to |
| 188 | the spoken feedback.</p> |
| 189 | |
| 190 | <p>Also, attempt to navigate your application using a directional controller, |
| 191 | instead of the touch screen. You can use a physical device with a d-pad or |
| 192 | trackball if one is available. If not, use the Android emulator and it's |
| 193 | simulated keyboard controls.</p> |
| 194 | |
| 195 | <p>Between the service providing feedback and the directional navigation through |
| 196 | your application, you should get a sense of what your application is like to |
| 197 | navigate without any visual cues. Fix problem areas as they appear, and you'll |
| 198 | end up with with a more accessible Android application.</p> |