AccessibilityDelegateCompat.java revision 956b013dfda37760b0232ed6d448900a546d2903
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 17package android.support.v4.view; 18 19import android.os.Build; 20import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; 21import android.support.v4.view.accessibility.AccessibilityNodeProviderCompat; 22import android.view.View; 23import android.view.ViewGroup; 24import android.view.accessibility.AccessibilityEvent; 25 26/** 27 * Helper for accessing {@link View.AccessibilityDelegate} introduced after 28 * API level 4 in a backwards compatible fashion. 29 */ 30public class AccessibilityDelegateCompat { 31 32 static interface AccessibilityDelegateImpl { 33 public Object newAccessiblityDelegateDefaultImpl(); 34 public Object newAccessiblityDelegateBridge(AccessibilityDelegateCompat listener); 35 public boolean dispatchPopulateAccessibilityEvent(Object delegate, View host, 36 AccessibilityEvent event); 37 public void onInitializeAccessibilityEvent(Object delegate, View host, 38 AccessibilityEvent event); 39 public void onInitializeAccessibilityNodeInfo(Object delegate, View host, 40 AccessibilityNodeInfoCompat info); 41 public void onPopulateAccessibilityEvent(Object delegate, View host, 42 AccessibilityEvent event); 43 public boolean onRequestSendAccessibilityEvent(Object delegate, ViewGroup host, View child, 44 AccessibilityEvent event); 45 public void sendAccessibilityEvent(Object delegate, View host, int eventType); 46 public void sendAccessibilityEventUnchecked(Object delegate, View host, 47 AccessibilityEvent event); 48 public AccessibilityNodeProviderCompat getAccessibilityNodeProvider(Object delegate, 49 View host); 50 } 51 52 static class AccessibilityDelegateStubImpl implements AccessibilityDelegateImpl { 53 public Object newAccessiblityDelegateDefaultImpl() { 54 return null; 55 } 56 57 @Override 58 public Object newAccessiblityDelegateBridge(AccessibilityDelegateCompat listener) { 59 return null; 60 } 61 62 @Override 63 public boolean dispatchPopulateAccessibilityEvent(Object delegate, View host, 64 AccessibilityEvent event) { 65 return false; 66 } 67 68 @Override 69 public void onInitializeAccessibilityEvent(Object delegate, View host, 70 AccessibilityEvent event) { 71 72 } 73 74 @Override 75 public void onInitializeAccessibilityNodeInfo(Object delegate, View host, 76 AccessibilityNodeInfoCompat info) { 77 78 } 79 80 @Override 81 public void onPopulateAccessibilityEvent(Object delegate, View host, 82 AccessibilityEvent event) { 83 84 } 85 86 @Override 87 public boolean onRequestSendAccessibilityEvent(Object delegate, ViewGroup host, View child, 88 AccessibilityEvent event) { 89 return true; 90 } 91 92 @Override 93 public void sendAccessibilityEvent(Object delegate, View host, int eventType) { 94 95 } 96 97 @Override 98 public void sendAccessibilityEventUnchecked(Object delegate, View host, 99 AccessibilityEvent event) { 100 101 } 102 103 @Override 104 public AccessibilityNodeProviderCompat getAccessibilityNodeProvider(Object delegate, 105 View host) { 106 return null; 107 } 108 } 109 110 static class AccessibilityDelegateIcsImpl extends AccessibilityDelegateStubImpl { 111 @Override 112 public Object newAccessiblityDelegateDefaultImpl() { 113 return AccessibilityDelegateCompatIcs.newAccessibilityDelegateDefaultImpl(); 114 } 115 116 @Override 117 public Object newAccessiblityDelegateBridge(final AccessibilityDelegateCompat compat) { 118 return AccessibilityDelegateCompatIcs.newAccessibilityDelegateBridge( 119 new AccessibilityDelegateCompatIcs.AccessibilityDelegateBridge() { 120 @Override 121 public boolean dispatchPopulateAccessibilityEvent(View host, 122 AccessibilityEvent event) { 123 return compat.dispatchPopulateAccessibilityEvent(host, event); 124 } 125 126 @Override 127 public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { 128 compat.onInitializeAccessibilityEvent(host, event); 129 } 130 131 @Override 132 public void onInitializeAccessibilityNodeInfo(View host, Object info) { 133 compat.onInitializeAccessibilityNodeInfo(host, 134 new AccessibilityNodeInfoCompat(info)); 135 } 136 137 @Override 138 public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) { 139 compat.onPopulateAccessibilityEvent(host, event); 140 } 141 142 @Override 143 public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child, 144 AccessibilityEvent event) { 145 return compat.onRequestSendAccessibilityEvent(host, child, event); 146 } 147 148 @Override 149 public void sendAccessibilityEvent(View host, int eventType) { 150 compat.sendAccessibilityEvent(host, eventType); 151 } 152 153 @Override 154 public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) { 155 compat.sendAccessibilityEventUnchecked(host, event); 156 } 157 }); 158 } 159 160 @Override 161 public boolean dispatchPopulateAccessibilityEvent(Object delegate, View host, 162 AccessibilityEvent event) { 163 return AccessibilityDelegateCompatIcs.dispatchPopulateAccessibilityEvent(delegate, 164 host, event); 165 } 166 167 @Override 168 public void onInitializeAccessibilityEvent(Object delegate, View host, 169 AccessibilityEvent event) { 170 AccessibilityDelegateCompatIcs.onInitializeAccessibilityEvent(delegate, host, event); 171 } 172 173 @Override 174 public void onInitializeAccessibilityNodeInfo(Object delegate, View host, 175 AccessibilityNodeInfoCompat info) { 176 AccessibilityDelegateCompatIcs.onInitializeAccessibilityNodeInfo(delegate, host, 177 info.getInfo()); 178 } 179 180 @Override 181 public void onPopulateAccessibilityEvent(Object delegate, View host, 182 AccessibilityEvent event) { 183 AccessibilityDelegateCompatIcs.onPopulateAccessibilityEvent(delegate, host, event); 184 } 185 186 @Override 187 public boolean onRequestSendAccessibilityEvent(Object delegate, ViewGroup host, View child, 188 AccessibilityEvent event) { 189 return AccessibilityDelegateCompatIcs.onRequestSendAccessibilityEvent(delegate, host, 190 child, event); 191 } 192 193 @Override 194 public void sendAccessibilityEvent(Object delegate, View host, int eventType) { 195 AccessibilityDelegateCompatIcs.sendAccessibilityEvent(delegate, host, eventType); 196 } 197 198 @Override 199 public void sendAccessibilityEventUnchecked(Object delegate, View host, 200 AccessibilityEvent event) { 201 AccessibilityDelegateCompatIcs.sendAccessibilityEventUnchecked(delegate, host, event); 202 } 203 } 204 205 static class AccessibilityDelegateJellyBeanImpl extends AccessibilityDelegateIcsImpl { 206 @Override 207 public Object newAccessiblityDelegateBridge(final AccessibilityDelegateCompat compat) { 208 return AccessibilityDelegateCompatJellyBean.newAccessibilityDelegateBridge( 209 new AccessibilityDelegateCompatJellyBean 210 .AccessibilityDelegateBridgeJellyBean() { 211 @Override 212 public boolean dispatchPopulateAccessibilityEvent(View host, 213 AccessibilityEvent event) { 214 return compat.dispatchPopulateAccessibilityEvent(host, event); 215 } 216 217 @Override 218 public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { 219 compat.onInitializeAccessibilityEvent(host, event); 220 } 221 222 @Override 223 public void onInitializeAccessibilityNodeInfo(View host, Object info) { 224 compat.onInitializeAccessibilityNodeInfo(host, 225 new AccessibilityNodeInfoCompat(info)); 226 } 227 228 @Override 229 public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) { 230 compat.onPopulateAccessibilityEvent(host, event); 231 } 232 233 @Override 234 public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child, 235 AccessibilityEvent event) { 236 return compat.onRequestSendAccessibilityEvent(host, child, event); 237 } 238 239 @Override 240 public void sendAccessibilityEvent(View host, int eventType) { 241 compat.sendAccessibilityEvent(host, eventType); 242 } 243 244 @Override 245 public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) { 246 compat.sendAccessibilityEventUnchecked(host, event); 247 } 248 249 @Override 250 public Object getAccessibilityNodeProvider(View host) { 251 return compat.getAccessibilityNodeProvider(host).getProvider(); 252 } 253 }); 254 } 255 256 @Override 257 public AccessibilityNodeProviderCompat getAccessibilityNodeProvider(Object delegate, 258 View host) { 259 Object provider = AccessibilityDelegateCompatJellyBean.getAccessibilityNodeProvider( 260 delegate, host); 261 if (provider != null) { 262 return new AccessibilityNodeProviderCompat(provider); 263 } 264 return null; 265 } 266 } 267 268 private static final AccessibilityDelegateImpl IMPL; 269 private static final Object DEFAULT_DELEGATE; 270 271 static { 272 // TODO: Update the conditional to use SDK_INT when we have an SDK version set. 273 // (tracked by bug:5947249) 274 if (Build.VERSION.CODENAME.equals("JellyBean")) { // JellyBean 275 IMPL = new AccessibilityDelegateJellyBeanImpl(); 276 } else if (Build.VERSION.SDK_INT >= 14) { // ICS 277 IMPL = new AccessibilityDelegateIcsImpl(); 278 } else { 279 IMPL = new AccessibilityDelegateStubImpl(); 280 } 281 DEFAULT_DELEGATE = IMPL.newAccessiblityDelegateDefaultImpl(); 282 } 283 284 final Object mBridge; 285 286 /** 287 * Creates a new instance. 288 */ 289 public AccessibilityDelegateCompat() { 290 mBridge = IMPL.newAccessiblityDelegateBridge(this); 291 } 292 293 /** 294 * @return The wrapped bridge implementation. 295 */ 296 Object getBridge() { 297 return mBridge; 298 } 299 300 /** 301 * Sends an accessibility event of the given type. If accessibility is not 302 * enabled this method has no effect. 303 * <p> 304 * The default implementation behaves as {@link View#sendAccessibilityEvent(int) 305 * View#sendAccessibilityEvent(int)} for the case of no accessibility delegate 306 * been set. 307 * </p> 308 * 309 * @param host The View hosting the delegate. 310 * @param eventType The type of the event to send. 311 * 312 * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int) 313 */ 314 public void sendAccessibilityEvent(View host, int eventType) { 315 IMPL.sendAccessibilityEvent(DEFAULT_DELEGATE, host, eventType); 316 } 317 318 /** 319 * Sends an accessibility event. This method behaves exactly as 320 * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an 321 * empty {@link AccessibilityEvent} and does not perform a check whether 322 * accessibility is enabled. 323 * <p> 324 * The default implementation behaves as 325 * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent) 326 * View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for 327 * the case of no accessibility delegate been set. 328 * </p> 329 * 330 * @param host The View hosting the delegate. 331 * @param event The event to send. 332 * 333 * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent) 334 * View#sendAccessibilityEventUnchecked(AccessibilityEvent) 335 */ 336 public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) { 337 IMPL.sendAccessibilityEventUnchecked(DEFAULT_DELEGATE, host, event); 338 } 339 340 /** 341 * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then 342 * to its children for adding their text content to the event. 343 * <p> 344 * The default implementation behaves as 345 * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 346 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for 347 * the case of no accessibility delegate been set. 348 * </p> 349 * 350 * @param host The View hosting the delegate. 351 * @param event The event. 352 * @return True if the event population was completed. 353 * 354 * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 355 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 356 */ 357 public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) { 358 return IMPL.dispatchPopulateAccessibilityEvent(DEFAULT_DELEGATE, host, event); 359 } 360 361 /** 362 * Gives a chance to the host View to populate the accessibility event with its 363 * text content. 364 * <p> 365 * The default implementation behaves as 366 * {@link ViewCompat#onPopulateAccessibilityEvent(View, AccessibilityEvent) 367 * ViewCompat#onPopulateAccessibilityEvent(AccessibilityEvent)} for 368 * the case of no accessibility delegate been set. 369 * </p> 370 * 371 * @param host The View hosting the delegate. 372 * @param event The accessibility event which to populate. 373 * 374 * @see ViewCompat#onPopulateAccessibilityEvent(View ,AccessibilityEvent) 375 * ViewCompat#onPopulateAccessibilityEvent(View, AccessibilityEvent) 376 */ 377 public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) { 378 IMPL.onPopulateAccessibilityEvent(DEFAULT_DELEGATE, host, event); 379 } 380 381 /** 382 * Initializes an {@link AccessibilityEvent} with information about the 383 * the host View which is the event source. 384 * <p> 385 * The default implementation behaves as 386 * {@link ViewCompat#onInitializeAccessibilityEvent(View v, AccessibilityEvent event) 387 * ViewCompat#onInitalizeAccessibilityEvent(View v, AccessibilityEvent event)} for 388 * the case of no accessibility delegate been set. 389 * </p> 390 * 391 * @param host The View hosting the delegate. 392 * @param event The event to initialize. 393 * 394 * @see ViewCompat#onInitializeAccessibilityEvent(View, AccessibilityEvent) 395 * ViewCompat#onInitializeAccessibilityEvent(View, AccessibilityEvent) 396 */ 397 public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { 398 IMPL.onInitializeAccessibilityEvent(DEFAULT_DELEGATE, host, event); 399 } 400 401 /** 402 * Initializes an {@link AccessibilityNodeInfoCompat} with information about the host view. 403 * <p> 404 * The default implementation behaves as 405 * {@link ViewCompat#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfoCompat) 406 * ViewCompat#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfoCompat)} for 407 * the case of no accessibility delegate been set. 408 * </p> 409 * 410 * @param host The View hosting the delegate. 411 * @param info The instance to initialize. 412 * 413 * @see ViewCompat#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfoCompat) 414 * ViewCompat#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfoCompat) 415 */ 416 public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) { 417 IMPL.onInitializeAccessibilityNodeInfo(DEFAULT_DELEGATE, host, info); 418 } 419 420 /** 421 * Called when a child of the host View has requested sending an 422 * {@link AccessibilityEvent} and gives an opportunity to the parent (the host) 423 * to augment the event. 424 * <p> 425 * The default implementation behaves as 426 * {@link ViewGroupCompat#onRequestSendAccessibilityEvent(ViewGroup, View, AccessibilityEvent) 427 * ViewGroupCompat#onRequestSendAccessibilityEvent(ViewGroup, View, AccessibilityEvent)} for 428 * the case of no accessibility delegate been set. 429 * </p> 430 * 431 * @param host The View hosting the delegate. 432 * @param child The child which requests sending the event. 433 * @param event The event to be sent. 434 * @return True if the event should be sent 435 * 436 * @see ViewGroupCompat#onRequestSendAccessibilityEvent(ViewGroup, View, AccessibilityEvent) 437 * ViewGroupCompat#onRequestSendAccessibilityEvent(ViewGroup, View, AccessibilityEvent) 438 */ 439 public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child, 440 AccessibilityEvent event) { 441 return IMPL.onRequestSendAccessibilityEvent(DEFAULT_DELEGATE, host, child, event); 442 } 443 444 /** 445 * Gets the provider for managing a virtual view hierarchy rooted at this View 446 * and reported to {@link android.accessibilityservice.AccessibilityService}s 447 * that explore the window content. 448 * <p> 449 * The default implementation behaves as 450 * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for 451 * the case of no accessibility delegate been set. 452 * </p> 453 * 454 * @return The provider. 455 * 456 * @see AccessibilityNodeProviderCompat 457 */ 458 public AccessibilityNodeProviderCompat getAccessibilityNodeProvider(View host) { 459 return IMPL.getAccessibilityNodeProvider(DEFAULT_DELEGATE, host); 460 } 461} 462