1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.view.accessibility; 18 19 import android.accessibilityservice.AccessibilityService; 20 import android.os.Bundle; 21 import android.view.View; 22 23 import java.util.List; 24 25 /** 26 * This class is the contract a client should implement to enable support of a 27 * virtual view hierarchy rooted at a given view for accessibility purposes. A virtual 28 * view hierarchy is a tree of imaginary Views that is reported as a part of the view 29 * hierarchy when an {@link AccessibilityService} explores the window content. 30 * Since the virtual View tree does not exist this class is responsible for 31 * managing the {@link AccessibilityNodeInfo}s describing that tree to accessibility 32 * services. 33 * </p> 34 * <p> 35 * The main use case of these APIs is to enable a custom view that draws complex content, 36 * for example a monthly calendar grid, to be presented as a tree of logical nodes, 37 * for example month days each containing events, thus conveying its logical structure. 38 * <p> 39 * <p> 40 * A typical use case is to override {@link View#getAccessibilityNodeProvider()} of the 41 * View that is a root of a virtual View hierarchy to return an instance of this class. 42 * In such a case this instance is responsible for managing {@link AccessibilityNodeInfo}s 43 * describing the virtual sub-tree rooted at the View including the one representing the 44 * View itself. Similarly the returned instance is responsible for performing accessibility 45 * actions on any virtual view or the root view itself. For example: 46 * </p> 47 * <div> 48 * <div class="ds-selector-tabs"><section><h3 id="kotlin">Kotlin</h3> 49 * <pre class="prettyprint lang-kotlin"> 50 * // "view" is the View instance on which this class performs accessibility functions. 51 * class MyCalendarViewAccessibilityDelegate( 52 * private var view: MyCalendarView) : AccessibilityDelegate() { 53 * override fun getAccessibilityNodeProvider(host: View): AccessibilityNodeProvider { 54 * return object : AccessibilityNodeProvider() { 55 * override fun createAccessibilityNodeInfo(virtualViewId: Int): 56 * AccessibilityNodeInfo? { 57 * when (virtualViewId) { 58 * <var>host-view-id</var> -> { 59 * val node = AccessibilityNodeInfo.obtain(view) 60 * node.addChild(view, <var>child-view-id</var>) 61 * // Set other attributes like screenReaderFocusable 62 * // and contentDescription. 63 * return node 64 * } 65 * <var>child-view-id</var> -> { 66 * val node = AccessibilityNodeInfo 67 * .obtain(view, virtualViewId) 68 * node.setParent(view) 69 * node.addAction(ACTION_SCROLL_UP) 70 * node.addAction(ACTION_SCROLL_DOWN) 71 * // Set other attributes like focusable and visibleToUser. 72 * node.setBoundsInScreen( 73 * Rect(<var>coords-of-edges-relative-to-screen</var>)) 74 * return node 75 * } 76 * else -> return null 77 * } 78 * } 79 * 80 * override fun performAction( 81 * virtualViewId: Int, 82 * action: Int, 83 * arguments: Bundle 84 * ): Boolean { 85 * if (virtualViewId == <var>host-view-id</var>) { 86 * return view.performAccessibilityAction(action, arguments) 87 * } 88 * when (action) { 89 * ACTION_SCROLL_UP.id -> { 90 * // Implement logic in a separate method. 91 * navigateToPreviousMonth() 92 * 93 * return true 94 * } 95 * ACTION_SCROLL_DOWN.id -> 96 * // Implement logic in a separate method. 97 * navigateToNextMonth() 98 * 99 * return true 100 * else -> return false 101 * } 102 * } 103 * } 104 * } 105 * } 106 * </pre> 107 * </section><section><h3 id="java">Java</h3> 108 * <pre class="prettyprint lang-java"> 109 * final class MyCalendarViewAccessibilityDelegate extends AccessibilityDelegate { 110 * // The View instance on which this class performs accessibility functions. 111 * private final MyCalendarView view; 112 * 113 * MyCalendarViewAccessibilityDelegate(MyCalendarView view) { 114 * this.view = view; 115 * } 116 * 117 * @Override 118 * public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) { 119 * return new AccessibilityNodeProvider() { 120 * @Override 121 * @Nullable 122 * public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) { 123 * if (virtualViewId == <var>host-view-id</var>) { 124 * AccessibilityNodeInfo node = AccessibilityNodeInfo.obtain(view); 125 * node.addChild(view, <var>child-view-id</var>); 126 * // Set other attributes like screenReaderFocusable and contentDescription. 127 * return node; 128 * } else if (virtualViewId == <var>child-view-id</var>) { 129 * AccessibilityNodeInfo node = 130 * AccessibilityNodeInfo.obtain(view, virtualViewId); 131 * node.setParent(view); 132 * node.addAction(ACTION_SCROLL_UP); 133 * node.addAction(ACTION_SCROLL_DOWN); 134 * // Set other attributes like focusable and visibleToUser. 135 * node.setBoundsInScreen( 136 * new Rect(<var>coordinates-of-edges-relative-to-screen</var>)); 137 * return node; 138 * } else { 139 * return null; 140 * } 141 * } 142 * 143 * @Override 144 * public boolean performAction(int virtualViewId, int action, Bundle arguments) { 145 * if (virtualViewId == <var>host-view-id</var>) { 146 * return view.performAccessibilityAction(action, arguments); 147 * } 148 * 149 * if (action == ACTION_SCROLL_UP.getId()) { 150 * // Implement logic in a separate method. 151 * navigateToPreviousMonth(); 152 * 153 * return true; 154 * } else if (action == ACTION_SCROLL_DOWN.getId()) { 155 * // Implement logic in a separate method. 156 * navigateToNextMonth(); 157 * 158 * return true; 159 * } else { 160 * return false; 161 * } 162 * } 163 * }; 164 * } 165 * } 166 * </pre></section></div></div> 167 */ 168 public abstract class AccessibilityNodeProvider { 169 170 /** 171 * The virtual id for the hosting View. 172 */ 173 public static final int HOST_VIEW_ID = -1; 174 175 /** 176 * Returns an {@link AccessibilityNodeInfo} representing a virtual view, 177 * such as a descendant of the host View, with the given <code>virtualViewId</code> 178 * or the host View itself if <code>virtualViewId</code> equals to {@link #HOST_VIEW_ID}. 179 * <p> 180 * A virtual descendant is an imaginary View that is reported as a part of the view 181 * hierarchy for accessibility purposes. This enables custom views that draw complex 182 * content to report them selves as a tree of virtual views, thus conveying their 183 * logical structure. 184 * </p> 185 * <p> 186 * The implementer is responsible for obtaining an accessibility node info from the 187 * pool of reusable instances and setting the desired properties of the node info 188 * before returning it. 189 * </p> 190 * 191 * @param virtualViewId A client defined virtual view id. 192 * @return A populated {@link AccessibilityNodeInfo} for a virtual descendant or the 193 * host View. 194 * 195 * @see View#createAccessibilityNodeInfo() 196 * @see AccessibilityNodeInfo 197 */ createAccessibilityNodeInfo(int virtualViewId)198 public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) { 199 return null; 200 } 201 202 /** 203 * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the 204 * additional data. 205 * <p> 206 * This method only needs to be implemented if a virtual view offers to provide additional 207 * data. 208 * </p> 209 * 210 * @param virtualViewId The virtual view id used to create the node 211 * @param info The info to which to add the extra data 212 * @param extraDataKey A key specifying the type of extra data to add to the info. The 213 * extra data should be added to the {@link Bundle} returned by 214 * the info's {@link AccessibilityNodeInfo#getExtras} method. 215 * @param arguments A {@link Bundle} holding any arguments relevant for this request. 216 * 217 * @see AccessibilityNodeInfo#setAvailableExtraData(List) 218 */ addExtraDataToAccessibilityNodeInfo( int virtualViewId, AccessibilityNodeInfo info, String extraDataKey, Bundle arguments)219 public void addExtraDataToAccessibilityNodeInfo( 220 int virtualViewId, AccessibilityNodeInfo info, String extraDataKey, Bundle arguments) { 221 } 222 223 /** 224 * Performs an accessibility action on a virtual view, such as a descendant of the 225 * host View, with the given <code>virtualViewId</code> or the host View itself 226 * if <code>virtualViewId</code> equals to {@link #HOST_VIEW_ID}. 227 * 228 * @param virtualViewId A client defined virtual view id. 229 * @param action The action to perform. 230 * @param arguments Optional action arguments. 231 * @return True if the action was performed. 232 * 233 * @see View#performAccessibilityAction(int, Bundle) 234 * @see #createAccessibilityNodeInfo(int) 235 * @see AccessibilityNodeInfo 236 */ performAction(int virtualViewId, int action, Bundle arguments)237 public boolean performAction(int virtualViewId, int action, Bundle arguments) { 238 return false; 239 } 240 241 /** 242 * Finds {@link AccessibilityNodeInfo}s by text. The match is case insensitive 243 * containment. The search is relative to the virtual view, i.e. a descendant of the 244 * host View, with the given <code>virtualViewId</code> or the host View itself 245 * <code>virtualViewId</code> equals to {@link #HOST_VIEW_ID}. 246 * 247 * @param virtualViewId A client defined virtual view id which defined 248 * the root of the tree in which to perform the search. 249 * @param text The searched text. 250 * @return A list of node info. 251 * 252 * @see #createAccessibilityNodeInfo(int) 253 * @see AccessibilityNodeInfo 254 */ findAccessibilityNodeInfosByText(String text, int virtualViewId)255 public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByText(String text, 256 int virtualViewId) { 257 return null; 258 } 259 260 /** 261 * Find the virtual view, such as a descendant of the host View, that has the 262 * specified focus type. 263 * 264 * @param focus The focus to find. One of 265 * {@link AccessibilityNodeInfo#FOCUS_INPUT} or 266 * {@link AccessibilityNodeInfo#FOCUS_ACCESSIBILITY}. 267 * @return The node info of the focused view or null. 268 * @see AccessibilityNodeInfo#FOCUS_INPUT 269 * @see AccessibilityNodeInfo#FOCUS_ACCESSIBILITY 270 */ findFocus(int focus)271 public AccessibilityNodeInfo findFocus(int focus) { 272 return null; 273 } 274 } 275