AccessibilityDelegateCompat.java revision f3ed7c56e6c409d27c60f7d74c026906593c21d4
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 if (Build.VERSION.SDK_INT >= 16) { // JellyBean 273 IMPL = new AccessibilityDelegateJellyBeanImpl(); 274 } else if (Build.VERSION.SDK_INT >= 14) { // ICS 275 IMPL = new AccessibilityDelegateIcsImpl(); 276 } else { 277 IMPL = new AccessibilityDelegateStubImpl(); 278 } 279 DEFAULT_DELEGATE = IMPL.newAccessiblityDelegateDefaultImpl(); 280 } 281 282 final Object mBridge; 283 284 /** 285 * Creates a new instance. 286 */ 287 public AccessibilityDelegateCompat() { 288 mBridge = IMPL.newAccessiblityDelegateBridge(this); 289 } 290 291 /** 292 * @return The wrapped bridge implementation. 293 */ 294 Object getBridge() { 295 return mBridge; 296 } 297 298 /** 299 * Sends an accessibility event of the given type. If accessibility is not 300 * enabled this method has no effect. 301 * <p> 302 * The default implementation behaves as {@link View#sendAccessibilityEvent(int) 303 * View#sendAccessibilityEvent(int)} for the case of no accessibility delegate 304 * been set. 305 * </p> 306 * 307 * @param host The View hosting the delegate. 308 * @param eventType The type of the event to send. 309 * 310 * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int) 311 */ 312 public void sendAccessibilityEvent(View host, int eventType) { 313 IMPL.sendAccessibilityEvent(DEFAULT_DELEGATE, host, eventType); 314 } 315 316 /** 317 * Sends an accessibility event. This method behaves exactly as 318 * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an 319 * empty {@link AccessibilityEvent} and does not perform a check whether 320 * accessibility is enabled. 321 * <p> 322 * The default implementation behaves as 323 * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent) 324 * View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for 325 * the case of no accessibility delegate been set. 326 * </p> 327 * 328 * @param host The View hosting the delegate. 329 * @param event The event to send. 330 * 331 * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent) 332 * View#sendAccessibilityEventUnchecked(AccessibilityEvent) 333 */ 334 public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) { 335 IMPL.sendAccessibilityEventUnchecked(DEFAULT_DELEGATE, host, event); 336 } 337 338 /** 339 * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then 340 * to its children for adding their text content to the event. 341 * <p> 342 * The default implementation behaves as 343 * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 344 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for 345 * the case of no accessibility delegate been set. 346 * </p> 347 * 348 * @param host The View hosting the delegate. 349 * @param event The event. 350 * @return True if the event population was completed. 351 * 352 * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 353 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 354 */ 355 public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) { 356 return IMPL.dispatchPopulateAccessibilityEvent(DEFAULT_DELEGATE, host, event); 357 } 358 359 /** 360 * Gives a chance to the host View to populate the accessibility event with its 361 * text content. 362 * <p> 363 * The default implementation behaves as 364 * {@link ViewCompat#onPopulateAccessibilityEvent(View, AccessibilityEvent) 365 * ViewCompat#onPopulateAccessibilityEvent(AccessibilityEvent)} for 366 * the case of no accessibility delegate been set. 367 * </p> 368 * 369 * @param host The View hosting the delegate. 370 * @param event The accessibility event which to populate. 371 * 372 * @see ViewCompat#onPopulateAccessibilityEvent(View ,AccessibilityEvent) 373 * ViewCompat#onPopulateAccessibilityEvent(View, AccessibilityEvent) 374 */ 375 public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) { 376 IMPL.onPopulateAccessibilityEvent(DEFAULT_DELEGATE, host, event); 377 } 378 379 /** 380 * Initializes an {@link AccessibilityEvent} with information about the 381 * the host View which is the event source. 382 * <p> 383 * The default implementation behaves as 384 * {@link ViewCompat#onInitializeAccessibilityEvent(View v, AccessibilityEvent event) 385 * ViewCompat#onInitalizeAccessibilityEvent(View v, AccessibilityEvent event)} for 386 * the case of no accessibility delegate been set. 387 * </p> 388 * 389 * @param host The View hosting the delegate. 390 * @param event The event to initialize. 391 * 392 * @see ViewCompat#onInitializeAccessibilityEvent(View, AccessibilityEvent) 393 * ViewCompat#onInitializeAccessibilityEvent(View, AccessibilityEvent) 394 */ 395 public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { 396 IMPL.onInitializeAccessibilityEvent(DEFAULT_DELEGATE, host, event); 397 } 398 399 /** 400 * Initializes an {@link AccessibilityNodeInfoCompat} with information about the host view. 401 * <p> 402 * The default implementation behaves as 403 * {@link ViewCompat#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfoCompat) 404 * ViewCompat#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfoCompat)} for 405 * the case of no accessibility delegate been set. 406 * </p> 407 * 408 * @param host The View hosting the delegate. 409 * @param info The instance to initialize. 410 * 411 * @see ViewCompat#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfoCompat) 412 * ViewCompat#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfoCompat) 413 */ 414 public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) { 415 IMPL.onInitializeAccessibilityNodeInfo(DEFAULT_DELEGATE, host, info); 416 } 417 418 /** 419 * Called when a child of the host View has requested sending an 420 * {@link AccessibilityEvent} and gives an opportunity to the parent (the host) 421 * to augment the event. 422 * <p> 423 * The default implementation behaves as 424 * {@link ViewGroupCompat#onRequestSendAccessibilityEvent(ViewGroup, View, AccessibilityEvent) 425 * ViewGroupCompat#onRequestSendAccessibilityEvent(ViewGroup, View, AccessibilityEvent)} for 426 * the case of no accessibility delegate been set. 427 * </p> 428 * 429 * @param host The View hosting the delegate. 430 * @param child The child which requests sending the event. 431 * @param event The event to be sent. 432 * @return True if the event should be sent 433 * 434 * @see ViewGroupCompat#onRequestSendAccessibilityEvent(ViewGroup, View, AccessibilityEvent) 435 * ViewGroupCompat#onRequestSendAccessibilityEvent(ViewGroup, View, AccessibilityEvent) 436 */ 437 public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child, 438 AccessibilityEvent event) { 439 return IMPL.onRequestSendAccessibilityEvent(DEFAULT_DELEGATE, host, child, event); 440 } 441 442 /** 443 * Gets the provider for managing a virtual view hierarchy rooted at this View 444 * and reported to {@link android.accessibilityservice.AccessibilityService}s 445 * that explore the window content. 446 * <p> 447 * The default implementation behaves as 448 * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for 449 * the case of no accessibility delegate been set. 450 * </p> 451 * 452 * @return The provider. 453 * 454 * @see AccessibilityNodeProviderCompat 455 */ 456 public AccessibilityNodeProviderCompat getAccessibilityNodeProvider(View host) { 457 return IMPL.getAccessibilityNodeProvider(DEFAULT_DELEGATE, host); 458 } 459} 460