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 androidx.core.view.accessibility; 18 19 import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 20 21 import android.graphics.Rect; 22 import android.os.Build; 23 import android.os.Bundle; 24 import android.text.InputType; 25 import android.view.View; 26 import android.view.accessibility.AccessibilityNodeInfo; 27 28 import androidx.annotation.NonNull; 29 import androidx.annotation.Nullable; 30 import androidx.annotation.RestrictTo; 31 import androidx.core.accessibilityservice.AccessibilityServiceInfoCompat; 32 import androidx.core.os.BuildCompat; 33 import androidx.core.view.ViewCompat; 34 35 import java.util.ArrayList; 36 import java.util.Collections; 37 import java.util.List; 38 39 /** 40 * Helper for accessing {@link android.view.accessibility.AccessibilityNodeInfo} in a backwards 41 * compatible fashion. 42 */ 43 @SuppressWarnings("NewApi") 44 public class AccessibilityNodeInfoCompat { 45 46 public static class AccessibilityActionCompat { 47 48 /** 49 * Action that gives input focus to the node. 50 */ 51 public static final AccessibilityActionCompat ACTION_FOCUS = 52 new AccessibilityActionCompat( 53 AccessibilityNodeInfoCompat.ACTION_FOCUS, null); 54 55 /** 56 * Action that clears input focus of the node. 57 */ 58 public static final AccessibilityActionCompat ACTION_CLEAR_FOCUS = 59 new AccessibilityActionCompat( 60 AccessibilityNodeInfoCompat.ACTION_CLEAR_FOCUS, null); 61 62 /** 63 * Action that selects the node. 64 */ 65 public static final AccessibilityActionCompat ACTION_SELECT = 66 new AccessibilityActionCompat( 67 AccessibilityNodeInfoCompat.ACTION_SELECT, null); 68 69 /** 70 * Action that deselects the node. 71 */ 72 public static final AccessibilityActionCompat ACTION_CLEAR_SELECTION = 73 new AccessibilityActionCompat( 74 AccessibilityNodeInfoCompat.ACTION_CLEAR_SELECTION, null); 75 76 /** 77 * Action that clicks on the node info. 78 */ 79 public static final AccessibilityActionCompat ACTION_CLICK = 80 new AccessibilityActionCompat( 81 AccessibilityNodeInfoCompat.ACTION_CLICK, null); 82 83 /** 84 * Action that long clicks on the node. 85 */ 86 public static final AccessibilityActionCompat ACTION_LONG_CLICK = 87 new AccessibilityActionCompat( 88 AccessibilityNodeInfoCompat.ACTION_LONG_CLICK, null); 89 90 /** 91 * Action that gives accessibility focus to the node. 92 */ 93 public static final AccessibilityActionCompat ACTION_ACCESSIBILITY_FOCUS = 94 new AccessibilityActionCompat( 95 AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS, null); 96 97 /** 98 * Action that clears accessibility focus of the node. 99 */ 100 public static final AccessibilityActionCompat ACTION_CLEAR_ACCESSIBILITY_FOCUS = 101 new AccessibilityActionCompat( 102 AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null); 103 104 /** 105 * Action that requests to go to the next entity in this node's text 106 * at a given movement granularity. For example, move to the next character, 107 * word, etc. 108 * <p> 109 * <strong>Arguments:</strong> 110 * {@link AccessibilityNodeInfoCompat#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT 111 * AccessibilityNodeInfoCompat.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}, 112 * {@link AccessibilityNodeInfoCompat#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN 113 * AccessibilityNodeInfoCompat.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br> 114 * <strong>Example:</strong> Move to the previous character and do not extend selection. 115 * <code><pre><p> 116 * Bundle arguments = new Bundle(); 117 * arguments.putInt(AccessibilityNodeInfoCompat.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT, 118 * AccessibilityNodeInfoCompat.MOVEMENT_GRANULARITY_CHARACTER); 119 * arguments.putBoolean( 120 * AccessibilityNodeInfoCompat.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, false); 121 * info.performAction( 122 * AccessibilityActionCompat.ACTION_NEXT_AT_MOVEMENT_GRANULARITY.getId(), 123 * arguments); 124 * </code></pre></p> 125 * </p> 126 * 127 * @see AccessibilityNodeInfoCompat#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT 128 * AccessibilityNodeInfoCompat.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT 129 * @see AccessibilityNodeInfoCompat#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN 130 * AccessibilityNodeInfoCompat.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN 131 * 132 * @see AccessibilityNodeInfoCompat#setMovementGranularities(int) 133 * AccessibilityNodeInfoCompat.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN 134 * @see AccessibilityNodeInfoCompat#getMovementGranularities() 135 * AccessibilityNodeInfoCompat.getMovementGranularities() 136 * 137 * @see AccessibilityNodeInfoCompat#MOVEMENT_GRANULARITY_CHARACTER 138 * AccessibilityNodeInfoCompat.MOVEMENT_GRANULARITY_CHARACTER 139 * @see AccessibilityNodeInfoCompat#MOVEMENT_GRANULARITY_WORD 140 * AccessibilityNodeInfoCompat.MOVEMENT_GRANULARITY_WORD 141 * @see AccessibilityNodeInfoCompat#MOVEMENT_GRANULARITY_LINE 142 * AccessibilityNodeInfoCompat.MOVEMENT_GRANULARITY_LINE 143 * @see AccessibilityNodeInfoCompat#MOVEMENT_GRANULARITY_PARAGRAPH 144 * AccessibilityNodeInfoCompat.MOVEMENT_GRANULARITY_PARAGRAPH 145 * @see AccessibilityNodeInfoCompat#MOVEMENT_GRANULARITY_PAGE 146 * AccessibilityNodeInfoCompat.MOVEMENT_GRANULARITY_PAGE 147 */ 148 public static final AccessibilityActionCompat ACTION_NEXT_AT_MOVEMENT_GRANULARITY = 149 new AccessibilityActionCompat( 150 AccessibilityNodeInfoCompat.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, null); 151 152 /** 153 * Action that requests to go to the previous entity in this node's text 154 * at a given movement granularity. For example, move to the next character, 155 * word, etc. 156 * <p> 157 * <strong>Arguments:</strong> 158 * {@link AccessibilityNodeInfoCompat#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT 159 * AccessibilityNodeInfoCompat.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}, 160 * {@link AccessibilityNodeInfoCompat#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN 161 * AccessibilityNodeInfoCompat.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br> 162 * <strong>Example:</strong> Move to the next character and do not extend selection. 163 * <code><pre><p> 164 * Bundle arguments = new Bundle(); 165 * arguments.putInt(AccessibilityNodeInfoCompat.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT, 166 * AccessibilityNodeInfoCompat.MOVEMENT_GRANULARITY_CHARACTER); 167 * arguments.putBoolean( 168 * AccessibilityNodeInfoCompat.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, false); 169 * info.performAction( 170 * AccessibilityActionCompat.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY.getId(), 171 * arguments); 172 * </code></pre></p> 173 * </p> 174 * 175 * @see AccessibilityNodeInfoCompat#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT 176 * AccessibilityNodeInfoCompat.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT 177 * @see AccessibilityNodeInfoCompat#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN 178 * AccessibilityNodeInfoCompat.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN 179 * 180 * @see AccessibilityNodeInfoCompat#setMovementGranularities(int) 181 * AccessibilityNodeInfoCompat.setMovementGranularities(int) 182 * @see AccessibilityNodeInfoCompat#getMovementGranularities() 183 * AccessibilityNodeInfoCompat.getMovementGranularities() 184 * 185 * @see AccessibilityNodeInfoCompat#MOVEMENT_GRANULARITY_CHARACTER 186 * AccessibilityNodeInfoCompat.MOVEMENT_GRANULARITY_CHARACTER 187 * @see AccessibilityNodeInfoCompat#MOVEMENT_GRANULARITY_WORD 188 * AccessibilityNodeInfoCompat.MOVEMENT_GRANULARITY_WORD 189 * @see AccessibilityNodeInfoCompat#MOVEMENT_GRANULARITY_LINE 190 * AccessibilityNodeInfoCompat.MOVEMENT_GRANULARITY_LINE 191 * @see AccessibilityNodeInfoCompat#MOVEMENT_GRANULARITY_PARAGRAPH 192 * AccessibilityNodeInfoCompat.MOVEMENT_GRANULARITY_PARAGRAPH 193 * @see AccessibilityNodeInfoCompat#MOVEMENT_GRANULARITY_PAGE 194 * AccessibilityNodeInfoCompat.MOVEMENT_GRANULARITY_PAGE 195 */ 196 public static final AccessibilityActionCompat ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY = 197 new AccessibilityActionCompat( 198 AccessibilityNodeInfoCompat.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, null); 199 200 /** 201 * Action to move to the next HTML element of a given type. For example, move 202 * to the BUTTON, INPUT, TABLE, etc. 203 * <p> 204 * <strong>Arguments:</strong> 205 * {@link AccessibilityNodeInfoCompat#ACTION_ARGUMENT_HTML_ELEMENT_STRING 206 * AccessibilityNodeInfoCompat.ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br> 207 * <strong>Example:</strong> 208 * <code><pre><p> 209 * Bundle arguments = new Bundle(); 210 * arguments.putString( 211 * AccessibilityNodeInfoCompat.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON"); 212 * info.performAction( 213 * AccessibilityActionCompat.ACTION_NEXT_HTML_ELEMENT.getId(), arguments); 214 * </code></pre></p> 215 * </p> 216 */ 217 public static final AccessibilityActionCompat ACTION_NEXT_HTML_ELEMENT = 218 new AccessibilityActionCompat( 219 AccessibilityNodeInfoCompat.ACTION_NEXT_HTML_ELEMENT, null); 220 221 /** 222 * Action to move to the previous HTML element of a given type. For example, move 223 * to the BUTTON, INPUT, TABLE, etc. 224 * <p> 225 * <strong>Arguments:</strong> 226 * {@link AccessibilityNodeInfoCompat#ACTION_ARGUMENT_HTML_ELEMENT_STRING 227 * AccessibilityNodeInfoCompat.ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br> 228 * <strong>Example:</strong> 229 * <code><pre><p> 230 * Bundle arguments = new Bundle(); 231 * arguments.putString( 232 * AccessibilityNodeInfoCompat.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON"); 233 * info.performAction( 234 * AccessibilityActionCompat.ACTION_PREVIOUS_HTML_ELEMENT.getId(), arguments); 235 * </code></pre></p> 236 * </p> 237 */ 238 public static final AccessibilityActionCompat ACTION_PREVIOUS_HTML_ELEMENT = 239 new AccessibilityActionCompat( 240 AccessibilityNodeInfoCompat.ACTION_PREVIOUS_HTML_ELEMENT, null); 241 242 /** 243 * Action to scroll the node content forward. 244 */ 245 public static final AccessibilityActionCompat ACTION_SCROLL_FORWARD = 246 new AccessibilityActionCompat( 247 AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD, null); 248 249 /** 250 * Action to scroll the node content backward. 251 */ 252 public static final AccessibilityActionCompat ACTION_SCROLL_BACKWARD = 253 new AccessibilityActionCompat( 254 AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD, null); 255 256 /** 257 * Action to copy the current selection to the clipboard. 258 */ 259 public static final AccessibilityActionCompat ACTION_COPY = 260 new AccessibilityActionCompat( 261 AccessibilityNodeInfoCompat.ACTION_COPY, null); 262 263 /** 264 * Action to paste the current clipboard content. 265 */ 266 public static final AccessibilityActionCompat ACTION_PASTE = 267 new AccessibilityActionCompat( 268 AccessibilityNodeInfoCompat.ACTION_PASTE, null); 269 270 /** 271 * Action to cut the current selection and place it to the clipboard. 272 */ 273 public static final AccessibilityActionCompat ACTION_CUT = 274 new AccessibilityActionCompat( 275 AccessibilityNodeInfoCompat.ACTION_CUT, null); 276 277 /** 278 * Action to set the selection. Performing this action with no arguments 279 * clears the selection. 280 * <p> 281 * <strong>Arguments:</strong> 282 * {@link AccessibilityNodeInfoCompat#ACTION_ARGUMENT_SELECTION_START_INT 283 * AccessibilityNodeInfoCompat.ACTION_ARGUMENT_SELECTION_START_INT}, 284 * {@link AccessibilityNodeInfoCompat#ACTION_ARGUMENT_SELECTION_END_INT 285 * AccessibilityNodeInfoCompat.ACTION_ARGUMENT_SELECTION_END_INT}<br> 286 * <strong>Example:</strong> 287 * <code><pre><p> 288 * Bundle arguments = new Bundle(); 289 * arguments.putInt(AccessibilityNodeInfoCompat.ACTION_ARGUMENT_SELECTION_START_INT, 1); 290 * arguments.putInt(AccessibilityNodeInfoCompat.ACTION_ARGUMENT_SELECTION_END_INT, 2); 291 * info.performAction(AccessibilityActionCompat.ACTION_SET_SELECTION.getId(), arguments); 292 * </code></pre></p> 293 * </p> 294 * 295 * @see AccessibilityNodeInfoCompat#ACTION_ARGUMENT_SELECTION_START_INT 296 * AccessibilityNodeInfoCompat.ACTION_ARGUMENT_SELECTION_START_INT 297 * @see AccessibilityNodeInfoCompat#ACTION_ARGUMENT_SELECTION_END_INT 298 * AccessibilityNodeInfoCompat.ACTION_ARGUMENT_SELECTION_END_INT 299 */ 300 public static final AccessibilityActionCompat ACTION_SET_SELECTION = 301 new AccessibilityActionCompat( 302 AccessibilityNodeInfoCompat.ACTION_SET_SELECTION, null); 303 304 /** 305 * Action to expand an expandable node. 306 */ 307 public static final AccessibilityActionCompat ACTION_EXPAND = 308 new AccessibilityActionCompat( 309 AccessibilityNodeInfoCompat.ACTION_EXPAND, null); 310 311 /** 312 * Action to collapse an expandable node. 313 */ 314 public static final AccessibilityActionCompat ACTION_COLLAPSE = 315 new AccessibilityActionCompat( 316 AccessibilityNodeInfoCompat.ACTION_COLLAPSE, null); 317 318 /** 319 * Action to dismiss a dismissable node. 320 */ 321 public static final AccessibilityActionCompat ACTION_DISMISS = 322 new AccessibilityActionCompat( 323 AccessibilityNodeInfoCompat.ACTION_DISMISS, null); 324 325 /** 326 * Action that sets the text of the node. Performing the action without argument, 327 * using <code> null</code> or empty {@link CharSequence} will clear the text. This 328 * action will also put the cursor at the end of text. 329 * <p> 330 * <strong>Arguments:</strong> 331 * {@link AccessibilityNodeInfoCompat#ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE 332 * AccessibilityNodeInfoCompat.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE}<br> 333 * <strong>Example:</strong> 334 * <code><pre><p> 335 * Bundle arguments = new Bundle(); 336 * arguments.putCharSequence(AccessibilityNodeInfoCompat.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, 337 * "android"); 338 * info.performAction(AccessibilityActionCompat.ACTION_SET_TEXT.getId(), arguments); 339 * </code></pre></p> 340 */ 341 public static final AccessibilityActionCompat ACTION_SET_TEXT = 342 new AccessibilityActionCompat( 343 AccessibilityNodeInfoCompat.ACTION_SET_TEXT, null); 344 345 /** 346 * Action that requests the node make its bounding rectangle visible 347 * on the screen, scrolling if necessary just enough. 348 * 349 * @see View#requestRectangleOnScreen(Rect) 350 */ 351 public static final AccessibilityActionCompat ACTION_SHOW_ON_SCREEN = 352 new AccessibilityActionCompat(Build.VERSION.SDK_INT >= 23 353 ? AccessibilityNodeInfo.AccessibilityAction.ACTION_SHOW_ON_SCREEN : null); 354 355 /** 356 * Action that scrolls the node to make the specified collection 357 * position visible on screen. 358 * <p> 359 * <strong>Arguments:</strong> 360 * <ul> 361 * <li>{@link AccessibilityNodeInfoCompat#ACTION_ARGUMENT_ROW_INT}</li> 362 * <li>{@link AccessibilityNodeInfoCompat#ACTION_ARGUMENT_COLUMN_INT}</li> 363 * <ul> 364 * 365 * @see AccessibilityNodeInfoCompat#getCollectionInfo() 366 */ 367 public static final AccessibilityActionCompat ACTION_SCROLL_TO_POSITION = 368 new AccessibilityActionCompat(Build.VERSION.SDK_INT >= 23 369 ? AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_TO_POSITION 370 : null); 371 372 /** 373 * Action to scroll the node content up. 374 */ 375 public static final AccessibilityActionCompat ACTION_SCROLL_UP = 376 new AccessibilityActionCompat(Build.VERSION.SDK_INT >= 23 377 ? AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_UP : null); 378 379 /** 380 * Action to scroll the node content left. 381 */ 382 public static final AccessibilityActionCompat ACTION_SCROLL_LEFT = 383 new AccessibilityActionCompat(Build.VERSION.SDK_INT >= 23 384 ? AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_LEFT : null); 385 386 /** 387 * Action to scroll the node content down. 388 */ 389 public static final AccessibilityActionCompat ACTION_SCROLL_DOWN = 390 new AccessibilityActionCompat(Build.VERSION.SDK_INT >= 23 391 ? AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_DOWN : null); 392 393 /** 394 * Action to scroll the node content right. 395 */ 396 public static final AccessibilityActionCompat ACTION_SCROLL_RIGHT = 397 new AccessibilityActionCompat(Build.VERSION.SDK_INT >= 23 398 ? AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_RIGHT : null); 399 400 /** 401 * Action that context clicks the node. 402 */ 403 public static final AccessibilityActionCompat ACTION_CONTEXT_CLICK = 404 new AccessibilityActionCompat(Build.VERSION.SDK_INT >= 23 405 ? AccessibilityNodeInfo.AccessibilityAction.ACTION_CONTEXT_CLICK : null); 406 407 /** 408 * Action that sets progress between {@link RangeInfoCompat#getMin() RangeInfo.getMin()} and 409 * {@link RangeInfoCompat#getMax() RangeInfo.getMax()}. It should use the same value type as 410 * {@link RangeInfoCompat#getType() RangeInfo.getType()} 411 * <p> 412 * <strong>Arguments:</strong> 413 * {@link AccessibilityNodeInfoCompat#ACTION_ARGUMENT_PROGRESS_VALUE} 414 * 415 * @see RangeInfoCompat 416 */ 417 public static final AccessibilityActionCompat ACTION_SET_PROGRESS = 418 new AccessibilityActionCompat(Build.VERSION.SDK_INT >= 24 419 ? AccessibilityNodeInfo.AccessibilityAction.ACTION_SET_PROGRESS : null); 420 421 /** 422 * Action to move a window to a new location. 423 * <p> 424 * <strong>Arguments:</strong> 425 * {@link AccessibilityNodeInfoCompat#ACTION_ARGUMENT_MOVE_WINDOW_X} 426 * {@link AccessibilityNodeInfoCompat#ACTION_ARGUMENT_MOVE_WINDOW_Y} 427 */ 428 public static final AccessibilityActionCompat ACTION_MOVE_WINDOW = 429 new AccessibilityActionCompat(Build.VERSION.SDK_INT >= 26 430 ? AccessibilityNodeInfo.AccessibilityAction.ACTION_MOVE_WINDOW : null); 431 432 /** 433 * Action to show a tooltip. 434 */ 435 public static final AccessibilityActionCompat ACTION_SHOW_TOOLTIP = 436 new AccessibilityActionCompat(BuildCompat.isAtLeastP() 437 ? AccessibilityNodeInfo.AccessibilityAction.ACTION_SHOW_TOOLTIP : null); 438 439 /** 440 * Action to hide a tooltip. A node should expose this action only for views that are 441 * currently showing a tooltip. 442 */ 443 public static final AccessibilityActionCompat ACTION_HIDE_TOOLTIP = 444 new AccessibilityActionCompat(BuildCompat.isAtLeastP() 445 ? AccessibilityNodeInfo.AccessibilityAction.ACTION_HIDE_TOOLTIP : null); 446 447 final Object mAction; 448 449 /** 450 * Creates a new instance. 451 * 452 * @param actionId The action id. 453 * @param label The action label. 454 */ 455 public AccessibilityActionCompat(int actionId, CharSequence label) { 456 this(Build.VERSION.SDK_INT >= 21 457 ? new AccessibilityNodeInfo.AccessibilityAction(actionId, label) : null); 458 } 459 460 AccessibilityActionCompat(Object action) { 461 mAction = action; 462 } 463 464 /** 465 * Gets the id for this action. 466 * 467 * @return The action id. 468 */ 469 public int getId() { 470 if (Build.VERSION.SDK_INT >= 21) { 471 return ((AccessibilityNodeInfo.AccessibilityAction) mAction).getId(); 472 } else { 473 return 0; 474 } 475 } 476 477 /** 478 * Gets the label for this action. Its purpose is to describe the 479 * action to user. 480 * 481 * @return The label. 482 */ 483 public CharSequence getLabel() { 484 if (Build.VERSION.SDK_INT >= 21) { 485 return ((AccessibilityNodeInfo.AccessibilityAction) mAction).getLabel(); 486 } else { 487 return null; 488 } 489 } 490 } 491 492 /** 493 * Class with information if a node is a collection. 494 * <p> 495 * A collection of items has rows and columns and may be hierarchical. 496 * For example, a horizontal list is a collection with one column, as 497 * many rows as the list items, and is not hierarchical; A table is a 498 * collection with several rows, several columns, and is not hierarchical; 499 * A vertical tree is a hierarchical collection with one column and 500 * as many rows as the first level children. 501 * </p> 502 */ 503 public static class CollectionInfoCompat { 504 /** Selection mode where items are not selectable. */ 505 public static final int SELECTION_MODE_NONE = 0; 506 507 /** Selection mode where a single item may be selected. */ 508 public static final int SELECTION_MODE_SINGLE = 1; 509 510 /** Selection mode where multiple items may be selected. */ 511 public static final int SELECTION_MODE_MULTIPLE = 2; 512 513 final Object mInfo; 514 515 /** 516 * Returns a cached instance if such is available otherwise a new one. 517 * 518 * @param rowCount The number of rows. 519 * @param columnCount The number of columns. 520 * @param hierarchical Whether the collection is hierarchical. 521 * @param selectionMode The collection's selection mode, one of: 522 * <ul> 523 * <li>{@link #SELECTION_MODE_NONE} 524 * <li>{@link #SELECTION_MODE_SINGLE} 525 * <li>{@link #SELECTION_MODE_MULTIPLE} 526 * </ul> 527 * 528 * @return An instance. 529 */ 530 public static CollectionInfoCompat obtain(int rowCount, int columnCount, 531 boolean hierarchical, int selectionMode) { 532 if (Build.VERSION.SDK_INT >= 21) { 533 return new CollectionInfoCompat(AccessibilityNodeInfo.CollectionInfo.obtain( 534 rowCount, columnCount, hierarchical, selectionMode)); 535 } else if (Build.VERSION.SDK_INT >= 19) { 536 return new CollectionInfoCompat(AccessibilityNodeInfo.CollectionInfo.obtain( 537 rowCount, columnCount, hierarchical)); 538 } else { 539 return new CollectionInfoCompat(null); 540 } 541 } 542 543 /** 544 * Returns a cached instance if such is available otherwise a new one. 545 * 546 * @param rowCount The number of rows. 547 * @param columnCount The number of columns. 548 * @param hierarchical Whether the collection is hierarchical. 549 * 550 * @return An instance. 551 */ 552 public static CollectionInfoCompat obtain(int rowCount, int columnCount, 553 boolean hierarchical) { 554 if (Build.VERSION.SDK_INT >= 19) { 555 return new CollectionInfoCompat(AccessibilityNodeInfo.CollectionInfo.obtain( 556 rowCount, columnCount, hierarchical)); 557 } else { 558 return new CollectionInfoCompat(null); 559 } 560 } 561 562 CollectionInfoCompat(Object info) { 563 mInfo = info; 564 } 565 566 /** 567 * Gets the number of columns. 568 * 569 * @return The column count. 570 */ 571 public int getColumnCount() { 572 if (Build.VERSION.SDK_INT >= 19) { 573 return ((AccessibilityNodeInfo.CollectionInfo) mInfo).getColumnCount(); 574 } else { 575 return 0; 576 } 577 } 578 579 /** 580 * Gets the number of rows. 581 * 582 * @return The row count. 583 */ 584 public int getRowCount() { 585 if (Build.VERSION.SDK_INT >= 19) { 586 return ((AccessibilityNodeInfo.CollectionInfo) mInfo).getRowCount(); 587 } else { 588 return 0; 589 } 590 } 591 592 /** 593 * Gets if the collection is a hierarchically ordered. 594 * 595 * @return Whether the collection is hierarchical. 596 */ 597 public boolean isHierarchical() { 598 if (Build.VERSION.SDK_INT >= 19) { 599 return ((AccessibilityNodeInfo.CollectionInfo) mInfo).isHierarchical(); 600 } else { 601 return false; 602 } 603 } 604 605 /** 606 * Gets the collection's selection mode. 607 * 608 * @return The collection's selection mode, one of: 609 * <ul> 610 * <li>{@link #SELECTION_MODE_NONE} 611 * <li>{@link #SELECTION_MODE_SINGLE} 612 * <li>{@link #SELECTION_MODE_MULTIPLE} 613 * </ul> 614 */ 615 public int getSelectionMode() { 616 if (Build.VERSION.SDK_INT >= 21) { 617 return ((AccessibilityNodeInfo.CollectionInfo) mInfo).getSelectionMode(); 618 } else { 619 return 0; 620 } 621 } 622 } 623 624 /** 625 * Class with information if a node is a collection item. 626 * <p> 627 * A collection item is contained in a collection, it starts at 628 * a given row and column in the collection, and spans one or 629 * more rows and columns. For example, a header of two related 630 * table columns starts at the first row and the first column, 631 * spans one row and two columns. 632 * </p> 633 */ 634 public static class CollectionItemInfoCompat { 635 636 final Object mInfo; 637 638 /** 639 * Returns a cached instance if such is available otherwise a new one. 640 * 641 * @param rowIndex The row index at which the item is located. 642 * @param rowSpan The number of rows the item spans. 643 * @param columnIndex The column index at which the item is located. 644 * @param columnSpan The number of columns the item spans. 645 * @param heading Whether the item is a heading. This should be set to false and the newer 646 * {@link AccessibilityNodeInfoCompat#setHeading(boolean)} used to identify 647 * headings. 648 * @param selected Whether the item is selected. 649 * @return An instance. 650 */ 651 public static CollectionItemInfoCompat obtain(int rowIndex, int rowSpan, 652 int columnIndex, int columnSpan, boolean heading, boolean selected) { 653 if (Build.VERSION.SDK_INT >= 21) { 654 return new CollectionItemInfoCompat(AccessibilityNodeInfo.CollectionItemInfo.obtain( 655 rowIndex, rowSpan, columnIndex, columnSpan, heading, selected)); 656 } else if (Build.VERSION.SDK_INT >= 19) { 657 return new CollectionItemInfoCompat(AccessibilityNodeInfo.CollectionItemInfo.obtain( 658 rowIndex, rowSpan, columnIndex, columnSpan, heading)); 659 } else { 660 return new CollectionItemInfoCompat(null); 661 } 662 } 663 664 /** 665 * Returns a cached instance if such is available otherwise a new one. 666 * 667 * @param rowIndex The row index at which the item is located. 668 * @param rowSpan The number of rows the item spans. 669 * @param columnIndex The column index at which the item is located. 670 * @param columnSpan The number of columns the item spans. 671 * @param heading Whether the item is a heading. This should be set to false and the newer 672 * {@link AccessibilityNodeInfoCompat#setHeading(boolean)} used to identify 673 * headings. 674 * @return An instance. 675 */ 676 public static CollectionItemInfoCompat obtain(int rowIndex, int rowSpan, 677 int columnIndex, int columnSpan, boolean heading) { 678 if (Build.VERSION.SDK_INT >= 19) { 679 return new CollectionItemInfoCompat(AccessibilityNodeInfo.CollectionItemInfo.obtain( 680 rowIndex, rowSpan, columnIndex, columnSpan, heading)); 681 } else { 682 return new CollectionItemInfoCompat(null); 683 } 684 } 685 686 CollectionItemInfoCompat(Object info) { 687 mInfo = info; 688 } 689 690 /** 691 * Gets the column index at which the item is located. 692 * 693 * @return The column index. 694 */ 695 public int getColumnIndex() { 696 if (Build.VERSION.SDK_INT >= 19) { 697 return ((AccessibilityNodeInfo.CollectionItemInfo) mInfo).getColumnIndex(); 698 } else { 699 return 0; 700 } 701 } 702 703 /** 704 * Gets the number of columns the item spans. 705 * 706 * @return The column span. 707 */ 708 public int getColumnSpan() { 709 if (Build.VERSION.SDK_INT >= 19) { 710 return ((AccessibilityNodeInfo.CollectionItemInfo) mInfo).getColumnSpan(); 711 } else { 712 return 0; 713 } 714 } 715 716 /** 717 * Gets the row index at which the item is located. 718 * 719 * @return The row index. 720 */ 721 public int getRowIndex() { 722 if (Build.VERSION.SDK_INT >= 19) { 723 return ((AccessibilityNodeInfo.CollectionItemInfo) mInfo).getRowIndex(); 724 } else { 725 return 0; 726 } 727 } 728 729 /** 730 * Gets the number of rows the item spans. 731 * 732 * @return The row span. 733 */ 734 public int getRowSpan() { 735 if (Build.VERSION.SDK_INT >= 19) { 736 return ((AccessibilityNodeInfo.CollectionItemInfo) mInfo).getRowSpan(); 737 } else { 738 return 0; 739 } 740 } 741 742 /** 743 * Gets if the collection item is a heading. For example, section 744 * heading, table header, etc. 745 * 746 * @return If the item is a heading. 747 * @deprecated Use {@link AccessibilityNodeInfoCompat#isHeading()} 748 */ 749 public boolean isHeading() { 750 if (Build.VERSION.SDK_INT >= 19) { 751 return ((AccessibilityNodeInfo.CollectionItemInfo) mInfo).isHeading(); 752 } else { 753 return false; 754 } 755 } 756 757 /** 758 * Gets if the collection item is selected. 759 * 760 * @return If the item is selected. 761 */ 762 public boolean isSelected() { 763 if (Build.VERSION.SDK_INT >= 21) { 764 return ((AccessibilityNodeInfo.CollectionItemInfo) mInfo).isSelected(); 765 } else { 766 return false; 767 } 768 } 769 } 770 771 /** 772 * Class with information if a node is a range. 773 */ 774 public static class RangeInfoCompat { 775 /** Range type: integer. */ 776 public static final int RANGE_TYPE_INT = 0; 777 /** Range type: float. */ 778 public static final int RANGE_TYPE_FLOAT = 1; 779 /** Range type: percent with values from zero to one.*/ 780 public static final int RANGE_TYPE_PERCENT = 2; 781 782 /** 783 * Obtains a cached instance if such is available otherwise a new one. 784 * 785 * @param type The type of the range. 786 * @param min The min value. 787 * @param max The max value. 788 * @param current The current value. 789 * @return The instance 790 */ 791 public static RangeInfoCompat obtain(int type, float min, float max, float current) { 792 if (Build.VERSION.SDK_INT >= 19) { 793 return new RangeInfoCompat( 794 AccessibilityNodeInfo.RangeInfo.obtain(type, min, max, current)); 795 } else { 796 return new RangeInfoCompat(null); 797 } 798 } 799 800 final Object mInfo; 801 802 RangeInfoCompat(Object info) { 803 mInfo = info; 804 } 805 806 /** 807 * Gets the current value. 808 * 809 * @return The current value. 810 */ 811 public float getCurrent() { 812 if (Build.VERSION.SDK_INT >= 19) { 813 return ((AccessibilityNodeInfo.RangeInfo) mInfo).getCurrent(); 814 } else { 815 return 0; 816 } 817 } 818 819 /** 820 * Gets the max value. 821 * 822 * @return The max value. 823 */ 824 public float getMax() { 825 if (Build.VERSION.SDK_INT >= 19) { 826 return ((AccessibilityNodeInfo.RangeInfo) mInfo).getMax(); 827 } else { 828 return 0; 829 } 830 } 831 832 /** 833 * Gets the min value. 834 * 835 * @return The min value. 836 */ 837 public float getMin() { 838 if (Build.VERSION.SDK_INT >= 19) { 839 return ((AccessibilityNodeInfo.RangeInfo) mInfo).getMin(); 840 } else { 841 return 0; 842 } 843 } 844 845 /** 846 * Gets the range type. 847 * 848 * @return The range type. 849 * 850 * @see #RANGE_TYPE_INT 851 * @see #RANGE_TYPE_FLOAT 852 * @see #RANGE_TYPE_PERCENT 853 */ 854 public int getType() { 855 if (Build.VERSION.SDK_INT >= 19) { 856 return ((AccessibilityNodeInfo.RangeInfo) mInfo).getType(); 857 } else { 858 return RANGE_TYPE_INT; 859 } 860 } 861 } 862 863 private static final String ROLE_DESCRIPTION_KEY = 864 "AccessibilityNodeInfo.roleDescription"; 865 866 private static final String PANE_TITLE_KEY = 867 "androidx.view.accessibility.AccessibilityNodeInfoCompat.PANE_TITLE_KEY"; 868 869 private static final String TOOLTIP_TEXT_KEY = 870 "androidx.view.accessibility.AccessibilityNodeInfoCompat.TOOLTIP_TEXT_KEY"; 871 872 private static final String HINT_TEXT_KEY = 873 "androidx.view.accessibility.AccessibilityNodeInfoCompat.HINT_TEXT_KEY"; 874 875 private static final String BOOLEAN_PROPERTY_KEY = 876 "androidx.view.accessibility.AccessibilityNodeInfoCompat.BOOLEAN_PROPERTY_KEY"; 877 878 // These don't line up with the internal framework constants, since they are independent 879 // and we might as well get all 32 bits of utility here. 880 private static final int BOOLEAN_PROPERTY_SCREEN_READER_FOCUSABLE = 0x00000001; 881 private static final int BOOLEAN_PROPERTY_IS_HEADING = 0x00000002; 882 private static final int BOOLEAN_PROPERTY_IS_SHOWING_HINT = 0x00000004; 883 884 private final AccessibilityNodeInfo mInfo; 885 886 /** 887 * androidx.customview.widget.ExploreByTouchHelper.HOST_ID = -1; 888 * 889 * @hide 890 */ 891 @RestrictTo(LIBRARY_GROUP) 892 public int mParentVirtualDescendantId = -1; 893 894 // Actions introduced in IceCreamSandwich 895 896 /** 897 * Action that focuses the node. 898 */ 899 public static final int ACTION_FOCUS = 0x00000001; 900 901 /** 902 * Action that unfocuses the node. 903 */ 904 public static final int ACTION_CLEAR_FOCUS = 0x00000002; 905 906 /** 907 * Action that selects the node. 908 */ 909 public static final int ACTION_SELECT = 0x00000004; 910 911 /** 912 * Action that unselects the node. 913 */ 914 public static final int ACTION_CLEAR_SELECTION = 0x00000008; 915 916 /** 917 * Action that clicks on the node info. 918 */ 919 public static final int ACTION_CLICK = 0x00000010; 920 921 /** 922 * Action that long clicks on the node. 923 */ 924 public static final int ACTION_LONG_CLICK = 0x00000020; 925 926 // Actions introduced in JellyBean 927 928 /** 929 * Action that gives accessibility focus to the node. 930 */ 931 public static final int ACTION_ACCESSIBILITY_FOCUS = 0x00000040; 932 933 /** 934 * Action that clears accessibility focus of the node. 935 */ 936 public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 0x00000080; 937 938 /** 939 * Action that requests to go to the next entity in this node's text 940 * at a given movement granularity. For example, move to the next character, 941 * word, etc. 942 * <p> 943 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<, 944 * {@link #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br> 945 * <strong>Example:</strong> Move to the previous character and do not extend selection. 946 * <code><pre><p> 947 * Bundle arguments = new Bundle(); 948 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT, 949 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER); 950 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, 951 * false); 952 * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments); 953 * </code></pre></p> 954 * </p> 955 * 956 * @see #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT 957 * @see #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN 958 * 959 * @see #setMovementGranularities(int) 960 * @see #getMovementGranularities() 961 * 962 * @see #MOVEMENT_GRANULARITY_CHARACTER 963 * @see #MOVEMENT_GRANULARITY_WORD 964 * @see #MOVEMENT_GRANULARITY_LINE 965 * @see #MOVEMENT_GRANULARITY_PARAGRAPH 966 * @see #MOVEMENT_GRANULARITY_PAGE 967 */ 968 public static final int ACTION_NEXT_AT_MOVEMENT_GRANULARITY = 0x00000100; 969 970 /** 971 * Action that requests to go to the previous entity in this node's text 972 * at a given movement granularity. For example, move to the next character, 973 * word, etc. 974 * <p> 975 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<, 976 * {@link #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br> 977 * <strong>Example:</strong> Move to the next character and do not extend selection. 978 * <code><pre><p> 979 * Bundle arguments = new Bundle(); 980 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT, 981 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER); 982 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, 983 * false); 984 * info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, 985 * arguments); 986 * </code></pre></p> 987 * </p> 988 * 989 * @see #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT 990 * @see #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN 991 * 992 * @see #setMovementGranularities(int) 993 * @see #getMovementGranularities() 994 * 995 * @see #MOVEMENT_GRANULARITY_CHARACTER 996 * @see #MOVEMENT_GRANULARITY_WORD 997 * @see #MOVEMENT_GRANULARITY_LINE 998 * @see #MOVEMENT_GRANULARITY_PARAGRAPH 999 * @see #MOVEMENT_GRANULARITY_PAGE 1000 */ 1001 public static final int ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY = 0x00000200; 1002 1003 /** 1004 * Action to move to the next HTML element of a given type. For example, move 1005 * to the BUTTON, INPUT, TABLE, etc. 1006 * <p> 1007 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br> 1008 * <strong>Example:</strong> 1009 * <code><pre><p> 1010 * Bundle arguments = new Bundle(); 1011 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON"); 1012 * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT, arguments); 1013 * </code></pre></p> 1014 * </p> 1015 */ 1016 public static final int ACTION_NEXT_HTML_ELEMENT = 0x00000400; 1017 1018 /** 1019 * Action to move to the previous HTML element of a given type. For example, move 1020 * to the BUTTON, INPUT, TABLE, etc. 1021 * <p> 1022 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br> 1023 * <strong>Example:</strong> 1024 * <code><pre><p> 1025 * Bundle arguments = new Bundle(); 1026 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON"); 1027 * info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT, arguments); 1028 * </code></pre></p> 1029 * </p> 1030 */ 1031 public static final int ACTION_PREVIOUS_HTML_ELEMENT = 0x00000800; 1032 1033 /** 1034 * Action to scroll the node content forward. 1035 */ 1036 public static final int ACTION_SCROLL_FORWARD = 0x00001000; 1037 1038 /** 1039 * Action to scroll the node content backward. 1040 */ 1041 public static final int ACTION_SCROLL_BACKWARD = 0x00002000; 1042 1043 // Actions introduced in JellyBeanMr2 1044 1045 /** 1046 * Action to copy the current selection to the clipboard. 1047 */ 1048 public static final int ACTION_COPY = 0x00004000; 1049 1050 /** 1051 * Action to paste the current clipboard content. 1052 */ 1053 public static final int ACTION_PASTE = 0x00008000; 1054 1055 /** 1056 * Action to cut the current selection and place it to the clipboard. 1057 */ 1058 public static final int ACTION_CUT = 0x00010000; 1059 1060 /** 1061 * Action to set the selection. Performing this action with no arguments 1062 * clears the selection. 1063 * <p> 1064 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_SELECTION_START_INT}, 1065 * {@link #ACTION_ARGUMENT_SELECTION_END_INT}<br> 1066 * <strong>Example:</strong> 1067 * <code><pre><p> 1068 * Bundle arguments = new Bundle(); 1069 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 1); 1070 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 2); 1071 * info.performAction(AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments); 1072 * </code></pre></p> 1073 * </p> 1074 * 1075 * @see #ACTION_ARGUMENT_SELECTION_START_INT 1076 * @see #ACTION_ARGUMENT_SELECTION_END_INT 1077 */ 1078 public static final int ACTION_SET_SELECTION = 0x00020000; 1079 1080 /** 1081 * Action to expand an expandable node. 1082 */ 1083 public static final int ACTION_EXPAND = 0x00040000; 1084 1085 /** 1086 * Action to collapse an expandable node. 1087 */ 1088 public static final int ACTION_COLLAPSE = 0x00080000; 1089 1090 /** 1091 * Action to dismiss a dismissable node. 1092 */ 1093 public static final int ACTION_DISMISS = 0x00100000; 1094 1095 /** 1096 * Action that sets the text of the node. Performing the action without argument, using <code> 1097 * null</code> or empty {@link CharSequence} will clear the text. This action will also put the 1098 * cursor at the end of text. 1099 * <p> 1100 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE}<br> 1101 * <strong>Example:</strong> 1102 * <code><pre><p> 1103 * Bundle arguments = new Bundle(); 1104 * arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, 1105 * "android"); 1106 * info.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments); 1107 * </code></pre></p> 1108 */ 1109 public static final int ACTION_SET_TEXT = 0x00200000; 1110 1111 // Action arguments 1112 1113 /** 1114 * Argument for which movement granularity to be used when traversing the node text. 1115 * <p> 1116 * <strong>Type:</strong> int<br> 1117 * <strong>Actions:</strong> {@link #ACTION_NEXT_AT_MOVEMENT_GRANULARITY}, 1118 * {@link #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY} 1119 * </p> 1120 */ 1121 public static final String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT = 1122 "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT"; 1123 1124 /** 1125 * Argument for which HTML element to get moving to the next/previous HTML element. 1126 * <p> 1127 * <strong>Type:</strong> String<br> 1128 * <strong>Actions:</strong> {@link #ACTION_NEXT_HTML_ELEMENT}, 1129 * {@link #ACTION_PREVIOUS_HTML_ELEMENT} 1130 * </p> 1131 */ 1132 public static final String ACTION_ARGUMENT_HTML_ELEMENT_STRING = 1133 "ACTION_ARGUMENT_HTML_ELEMENT_STRING"; 1134 1135 /** 1136 * Argument for whether when moving at granularity to extend the selection 1137 * or to move it otherwise. 1138 * <p> 1139 * <strong>Type:</strong> boolean<br> 1140 * <strong>Actions:</strong> {@link #ACTION_NEXT_AT_MOVEMENT_GRANULARITY}, 1141 * {@link #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY} 1142 * </p> 1143 * 1144 * @see #ACTION_NEXT_AT_MOVEMENT_GRANULARITY 1145 * @see #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY 1146 */ 1147 public static final String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN = 1148 "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN"; 1149 1150 /** 1151 * Argument for specifying the selection start. 1152 * <p> 1153 * <strong>Type:</strong> int<br> 1154 * <strong>Actions:</strong> {@link #ACTION_SET_SELECTION} 1155 * </p> 1156 * 1157 * @see #ACTION_SET_SELECTION 1158 */ 1159 public static final String ACTION_ARGUMENT_SELECTION_START_INT = 1160 "ACTION_ARGUMENT_SELECTION_START_INT"; 1161 1162 /** 1163 * Argument for specifying the selection end. 1164 * <p> 1165 * <strong>Type:</strong> int<br> 1166 * <strong>Actions:</strong> {@link #ACTION_SET_SELECTION} 1167 * </p> 1168 * 1169 * @see #ACTION_SET_SELECTION 1170 */ 1171 public static final String ACTION_ARGUMENT_SELECTION_END_INT = 1172 "ACTION_ARGUMENT_SELECTION_END_INT"; 1173 1174 /** 1175 * Argument for specifying the text content to set 1176 * <p> 1177 * <strong>Type:</strong> CharSequence<br> 1178 * <strong>Actions:</strong> {@link #ACTION_SET_TEXT} 1179 * </p> 1180 * 1181 * @see #ACTION_SET_TEXT 1182 */ 1183 public static final String ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE = 1184 "ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE"; 1185 1186 /** 1187 * Argument for specifying the collection row to make visible on screen. 1188 * <p> 1189 * <strong>Type:</strong> int<br> 1190 * <strong>Actions:</strong> 1191 * <ul> 1192 * <li>{@link AccessibilityActionCompat#ACTION_SCROLL_TO_POSITION}</li> 1193 * </ul> 1194 * 1195 * @see AccessibilityActionCompat#ACTION_SCROLL_TO_POSITION 1196 */ 1197 public static final String ACTION_ARGUMENT_ROW_INT = 1198 "android.view.accessibility.action.ARGUMENT_ROW_INT"; 1199 1200 /** 1201 * Argument for specifying the collection column to make visible on screen. 1202 * <p> 1203 * <strong>Type:</strong> int<br> 1204 * <strong>Actions:</strong> 1205 * <ul> 1206 * <li>{@link AccessibilityActionCompat#ACTION_SCROLL_TO_POSITION}</li> 1207 * </ul> 1208 * 1209 * @see AccessibilityActionCompat#ACTION_SCROLL_TO_POSITION 1210 */ 1211 public static final String ACTION_ARGUMENT_COLUMN_INT = 1212 "android.view.accessibility.action.ARGUMENT_COLUMN_INT"; 1213 1214 /** 1215 * Argument for specifying the progress value to set. 1216 * <p> 1217 * <strong>Type:</strong> float<br> 1218 * <strong>Actions:</strong> 1219 * <ul> 1220 * <li>{@link AccessibilityActionCompat#ACTION_SET_PROGRESS}</li> 1221 * </ul> 1222 * 1223 * @see AccessibilityActionCompat#ACTION_SET_PROGRESS 1224 */ 1225 public static final String ACTION_ARGUMENT_PROGRESS_VALUE = 1226 "android.view.accessibility.action.ARGUMENT_PROGRESS_VALUE"; 1227 1228 /** 1229 * Argument for specifying the x coordinate to which to move a window. 1230 * <p> 1231 * <strong>Type:</strong> int<br> 1232 * <strong>Actions:</strong> 1233 * <ul> 1234 * <li>{@link AccessibilityActionCompat#ACTION_MOVE_WINDOW}</li> 1235 * </ul> 1236 * 1237 * @see AccessibilityActionCompat#ACTION_MOVE_WINDOW 1238 */ 1239 public static final String ACTION_ARGUMENT_MOVE_WINDOW_X = 1240 "ACTION_ARGUMENT_MOVE_WINDOW_X"; 1241 1242 /** 1243 * Argument for specifying the y coordinate to which to move a window. 1244 * <p> 1245 * <strong>Type:</strong> int<br> 1246 * <strong>Actions:</strong> 1247 * <ul> 1248 * <li>{@link AccessibilityActionCompat#ACTION_MOVE_WINDOW}</li> 1249 * </ul> 1250 * 1251 * @see AccessibilityActionCompat#ACTION_MOVE_WINDOW 1252 */ 1253 public static final String ACTION_ARGUMENT_MOVE_WINDOW_Y = 1254 "ACTION_ARGUMENT_MOVE_WINDOW_Y"; 1255 1256 // Focus types 1257 1258 /** 1259 * The input focus. 1260 */ 1261 public static final int FOCUS_INPUT = 1; 1262 1263 /** 1264 * The accessibility focus. 1265 */ 1266 public static final int FOCUS_ACCESSIBILITY = 2; 1267 1268 // Movement granularities 1269 1270 /** 1271 * Movement granularity bit for traversing the text of a node by character. 1272 */ 1273 public static final int MOVEMENT_GRANULARITY_CHARACTER = 0x00000001; 1274 1275 /** 1276 * Movement granularity bit for traversing the text of a node by word. 1277 */ 1278 public static final int MOVEMENT_GRANULARITY_WORD = 0x00000002; 1279 1280 /** 1281 * Movement granularity bit for traversing the text of a node by line. 1282 */ 1283 public static final int MOVEMENT_GRANULARITY_LINE = 0x00000004; 1284 1285 /** 1286 * Movement granularity bit for traversing the text of a node by paragraph. 1287 */ 1288 public static final int MOVEMENT_GRANULARITY_PARAGRAPH = 0x00000008; 1289 1290 /** 1291 * Movement granularity bit for traversing the text of a node by page. 1292 */ 1293 public static final int MOVEMENT_GRANULARITY_PAGE = 0x00000010; 1294 1295 /** 1296 * Creates a wrapper for info implementation. 1297 * 1298 * @param object The info to wrap. 1299 * @return A wrapper for if the object is not null, null otherwise. 1300 */ 1301 static AccessibilityNodeInfoCompat wrapNonNullInstance(Object object) { 1302 if (object != null) { 1303 return new AccessibilityNodeInfoCompat(object); 1304 } 1305 return null; 1306 } 1307 1308 /** 1309 * Creates a new instance wrapping an 1310 * {@link android.view.accessibility.AccessibilityNodeInfo}. 1311 * 1312 * @param info The info. 1313 * 1314 * @deprecated Use {@link #wrap(AccessibilityNodeInfo)} instead. 1315 */ 1316 @Deprecated 1317 public AccessibilityNodeInfoCompat(Object info) { 1318 mInfo = (AccessibilityNodeInfo) info; 1319 } 1320 1321 private AccessibilityNodeInfoCompat(AccessibilityNodeInfo info) { 1322 mInfo = info; 1323 } 1324 1325 /** 1326 * Creates a new instance wrapping an 1327 * {@link android.view.accessibility.AccessibilityNodeInfo}. 1328 * 1329 * @param info The info. 1330 */ 1331 public static AccessibilityNodeInfoCompat wrap(@NonNull AccessibilityNodeInfo info) { 1332 return new AccessibilityNodeInfoCompat(info); 1333 } 1334 1335 /** 1336 * @return The unwrapped {@link android.view.accessibility.AccessibilityNodeInfo}. 1337 */ 1338 public AccessibilityNodeInfo unwrap() { 1339 return mInfo; 1340 } 1341 1342 /** 1343 * @return The wrapped {@link android.view.accessibility.AccessibilityNodeInfo}. 1344 * 1345 * @deprecated Use {@link #unwrap()} instead. 1346 */ 1347 @Deprecated 1348 public Object getInfo() { 1349 return mInfo; 1350 } 1351 1352 /** 1353 * Returns a cached instance if such is available otherwise a new one and 1354 * sets the source. 1355 * 1356 * @return An instance. 1357 * @see #setSource(View) 1358 */ 1359 public static AccessibilityNodeInfoCompat obtain(View source) { 1360 return AccessibilityNodeInfoCompat.wrap(AccessibilityNodeInfo.obtain(source)); 1361 } 1362 1363 /** 1364 * Returns a cached instance if such is available otherwise a new one 1365 * and sets the source. 1366 * 1367 * @param root The root of the virtual subtree. 1368 * @param virtualDescendantId The id of the virtual descendant. 1369 * @return An instance. 1370 * 1371 * @see #setSource(View, int) 1372 */ 1373 public static AccessibilityNodeInfoCompat obtain(View root, int virtualDescendantId) { 1374 if (Build.VERSION.SDK_INT >= 16) { 1375 return AccessibilityNodeInfoCompat.wrapNonNullInstance( 1376 AccessibilityNodeInfo.obtain(root, virtualDescendantId)); 1377 } else { 1378 return null; 1379 } 1380 } 1381 1382 /** 1383 * Returns a cached instance if such is available otherwise a new one. 1384 * 1385 * @return An instance. 1386 */ 1387 public static AccessibilityNodeInfoCompat obtain() { 1388 return AccessibilityNodeInfoCompat.wrap(AccessibilityNodeInfo.obtain()); 1389 } 1390 1391 /** 1392 * Returns a cached instance if such is available or a new one is create. 1393 * The returned instance is initialized from the given <code>info</code>. 1394 * 1395 * @param info The other info. 1396 * @return An instance. 1397 */ 1398 public static AccessibilityNodeInfoCompat obtain(AccessibilityNodeInfoCompat info) { 1399 return AccessibilityNodeInfoCompat.wrap(AccessibilityNodeInfo.obtain(info.mInfo)); 1400 } 1401 1402 /** 1403 * Sets the source. 1404 * 1405 * @param source The info source. 1406 */ 1407 public void setSource(View source) { 1408 mInfo.setSource(source); 1409 } 1410 1411 /** 1412 * Sets the source to be a virtual descendant of the given <code>root</code>. 1413 * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root 1414 * is set as the source. 1415 * <p> 1416 * A virtual descendant is an imaginary View that is reported as a part of the view 1417 * hierarchy for accessibility purposes. This enables custom views that draw complex 1418 * content to report themselves as a tree of virtual views, thus conveying their 1419 * logical structure. 1420 * </p> 1421 * <p> 1422 * <strong>Note:</strong> Cannot be called from an 1423 * {@link android.accessibilityservice.AccessibilityService}. 1424 * This class is made immutable before being delivered to an AccessibilityService. 1425 * </p> 1426 * 1427 * @param root The root of the virtual subtree. 1428 * @param virtualDescendantId The id of the virtual descendant. 1429 */ 1430 public void setSource(View root, int virtualDescendantId) { 1431 if (Build.VERSION.SDK_INT >= 16) { 1432 mInfo.setSource(root, virtualDescendantId); 1433 } 1434 } 1435 1436 /** 1437 * Find the view that has the specified focus type. The search starts from 1438 * the view represented by this node info. 1439 * 1440 * @param focus The focus to find. One of {@link #FOCUS_INPUT} or 1441 * {@link #FOCUS_ACCESSIBILITY}. 1442 * @return The node info of the focused view or null. 1443 * 1444 * @see #FOCUS_INPUT 1445 * @see #FOCUS_ACCESSIBILITY 1446 */ 1447 public AccessibilityNodeInfoCompat findFocus(int focus) { 1448 if (Build.VERSION.SDK_INT >= 16) { 1449 return AccessibilityNodeInfoCompat.wrapNonNullInstance(mInfo.findFocus(focus)); 1450 } else { 1451 return null; 1452 } 1453 } 1454 1455 /** 1456 * Searches for the nearest view in the specified direction that can take 1457 * input focus. 1458 * 1459 * @param direction The direction. Can be one of: 1460 * {@link View#FOCUS_DOWN}, 1461 * {@link View#FOCUS_UP}, 1462 * {@link View#FOCUS_LEFT}, 1463 * {@link View#FOCUS_RIGHT}, 1464 * {@link View#FOCUS_FORWARD}, 1465 * {@link View#FOCUS_BACKWARD}. 1466 * 1467 * @return The node info for the view that can take accessibility focus. 1468 */ 1469 public AccessibilityNodeInfoCompat focusSearch(int direction) { 1470 if (Build.VERSION.SDK_INT >= 16) { 1471 return AccessibilityNodeInfoCompat.wrapNonNullInstance(mInfo.focusSearch(direction)); 1472 } else { 1473 return null; 1474 } 1475 } 1476 1477 /** 1478 * Gets the id of the window from which the info comes from. 1479 * 1480 * @return The window id. 1481 */ 1482 public int getWindowId() { 1483 return mInfo.getWindowId(); 1484 } 1485 1486 /** 1487 * Gets the number of children. 1488 * 1489 * @return The child count. 1490 */ 1491 public int getChildCount() { 1492 return mInfo.getChildCount(); 1493 } 1494 1495 /** 1496 * Get the child at given index. 1497 * <p> 1498 * <strong>Note:</strong> It is a client responsibility to recycle the 1499 * received info by calling {@link AccessibilityNodeInfoCompat#recycle()} to 1500 * avoid creating of multiple instances. 1501 * </p> 1502 * 1503 * @param index The child index. 1504 * @return The child node. 1505 * @throws IllegalStateException If called outside of an 1506 * AccessibilityService. 1507 */ 1508 public AccessibilityNodeInfoCompat getChild(int index) { 1509 return AccessibilityNodeInfoCompat.wrapNonNullInstance(mInfo.getChild(index)); 1510 } 1511 1512 /** 1513 * Adds a child. 1514 * <p> 1515 * <strong>Note:</strong> Cannot be called from an 1516 * {@link android.accessibilityservice.AccessibilityService}. This class is 1517 * made immutable before being delivered to an AccessibilityService. 1518 * </p> 1519 * 1520 * @param child The child. 1521 * @throws IllegalStateException If called from an AccessibilityService. 1522 */ 1523 public void addChild(View child) { 1524 mInfo.addChild(child); 1525 } 1526 1527 /** 1528 * Adds a virtual child which is a descendant of the given <code>root</code>. 1529 * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root 1530 * is added as a child. 1531 * <p> 1532 * A virtual descendant is an imaginary View that is reported as a part of the view 1533 * hierarchy for accessibility purposes. This enables custom views that draw complex 1534 * content to report them selves as a tree of virtual views, thus conveying their 1535 * logical structure. 1536 * </p> 1537 * 1538 * @param root The root of the virtual subtree. 1539 * @param virtualDescendantId The id of the virtual child. 1540 */ 1541 public void addChild(View root, int virtualDescendantId) { 1542 if (Build.VERSION.SDK_INT >= 16) { 1543 mInfo.addChild(root, virtualDescendantId); 1544 } 1545 } 1546 1547 /** 1548 * Removes a child. If the child was not previously added to the node, 1549 * calling this method has no effect. 1550 * <p> 1551 * <strong>Note:</strong> Cannot be called from an 1552 * {@link android.accessibilityservice.AccessibilityService}. 1553 * This class is made immutable before being delivered to an AccessibilityService. 1554 * </p> 1555 * 1556 * @param child The child. 1557 * @return true if the child was present 1558 * 1559 * @throws IllegalStateException If called from an AccessibilityService. 1560 */ 1561 public boolean removeChild(View child) { 1562 if (Build.VERSION.SDK_INT >= 21) { 1563 return mInfo.removeChild(child); 1564 } else { 1565 return false; 1566 } 1567 } 1568 1569 /** 1570 * Removes a virtual child which is a descendant of the given 1571 * <code>root</code>. If the child was not previously added to the node, 1572 * calling this method has no effect. 1573 * 1574 * @param root The root of the virtual subtree. 1575 * @param virtualDescendantId The id of the virtual child. 1576 * @return true if the child was present 1577 * @see #addChild(View, int) 1578 */ 1579 public boolean removeChild(View root, int virtualDescendantId) { 1580 if (Build.VERSION.SDK_INT >= 21) { 1581 return mInfo.removeChild(root, virtualDescendantId); 1582 } else { 1583 return false; 1584 } 1585 } 1586 1587 /** 1588 * Gets the actions that can be performed on the node. 1589 * 1590 * @return The bit mask of with actions. 1591 * @see android.view.accessibility.AccessibilityNodeInfo#ACTION_FOCUS 1592 * @see android.view.accessibility.AccessibilityNodeInfo#ACTION_CLEAR_FOCUS 1593 * @see android.view.accessibility.AccessibilityNodeInfo#ACTION_SELECT 1594 * @see android.view.accessibility.AccessibilityNodeInfo#ACTION_CLEAR_SELECTION 1595 */ 1596 public int getActions() { 1597 return mInfo.getActions(); 1598 } 1599 1600 /** 1601 * Adds an action that can be performed on the node. 1602 * <p> 1603 * <strong>Note:</strong> Cannot be called from an 1604 * {@link android.accessibilityservice.AccessibilityService}. This class is 1605 * made immutable before being delivered to an AccessibilityService. 1606 * </p> 1607 * 1608 * @param action The action. 1609 * @throws IllegalStateException If called from an AccessibilityService. 1610 */ 1611 public void addAction(int action) { 1612 mInfo.addAction(action); 1613 } 1614 1615 /** 1616 * Adds an action that can be performed on the node. 1617 * <p> 1618 * <strong>Note:</strong> Cannot be called from an 1619 * {@link android.accessibilityservice.AccessibilityService}. This class is 1620 * made immutable before being delivered to an AccessibilityService. 1621 * </p> 1622 * 1623 * @param action The action. 1624 * @throws IllegalStateException If called from an AccessibilityService. 1625 */ 1626 public void addAction(AccessibilityActionCompat action) { 1627 if (Build.VERSION.SDK_INT >= 21) { 1628 mInfo.addAction((AccessibilityNodeInfo.AccessibilityAction) action.mAction); 1629 } 1630 } 1631 1632 /** 1633 * Removes an action that can be performed on the node. If the action was 1634 * not already added to the node, calling this method has no effect. 1635 * <p> 1636 * <strong>Note:</strong> Cannot be called from an 1637 * {@link android.accessibilityservice.AccessibilityService}. 1638 * This class is made immutable before being delivered to an AccessibilityService. 1639 * </p> 1640 * 1641 * @param action The action to be removed. 1642 * @return The action removed from the list of actions. 1643 * 1644 * @throws IllegalStateException If called from an AccessibilityService. 1645 */ 1646 public boolean removeAction(AccessibilityActionCompat action) { 1647 if (Build.VERSION.SDK_INT >= 21) { 1648 return mInfo.removeAction((AccessibilityNodeInfo.AccessibilityAction) action.mAction); 1649 } else { 1650 return false; 1651 } 1652 } 1653 1654 /** 1655 * Performs an action on the node. 1656 * <p> 1657 * <strong>Note:</strong> An action can be performed only if the request is 1658 * made from an {@link android.accessibilityservice.AccessibilityService}. 1659 * </p> 1660 * 1661 * @param action The action to perform. 1662 * @return True if the action was performed. 1663 * @throws IllegalStateException If called outside of an 1664 * AccessibilityService. 1665 */ 1666 public boolean performAction(int action) { 1667 return mInfo.performAction(action); 1668 } 1669 1670 /** 1671 * Performs an action on the node. 1672 * <p> 1673 * <strong>Note:</strong> An action can be performed only if the request is made 1674 * from an {@link android.accessibilityservice.AccessibilityService}. 1675 * </p> 1676 * 1677 * @param action The action to perform. 1678 * @param arguments A bundle with additional arguments. 1679 * @return True if the action was performed. 1680 * 1681 * @throws IllegalStateException If called outside of an AccessibilityService. 1682 */ 1683 public boolean performAction(int action, Bundle arguments) { 1684 if (Build.VERSION.SDK_INT >= 16) { 1685 return mInfo.performAction(action, arguments); 1686 } else { 1687 return false; 1688 } 1689 } 1690 1691 /** 1692 * Sets the movement granularities for traversing the text of this node. 1693 * <p> 1694 * <strong>Note:</strong> Cannot be called from an 1695 * {@link android.accessibilityservice.AccessibilityService}. 1696 * This class is made immutable before being delivered to an AccessibilityService. 1697 * </p> 1698 * 1699 * @param granularities The bit mask with granularities. 1700 * 1701 * @throws IllegalStateException If called from an AccessibilityService. 1702 */ 1703 public void setMovementGranularities(int granularities) { 1704 if (Build.VERSION.SDK_INT >= 16) { 1705 mInfo.setMovementGranularities(granularities); 1706 } 1707 } 1708 1709 /** 1710 * Gets the movement granularities for traversing the text of this node. 1711 * 1712 * @return The bit mask with granularities. 1713 */ 1714 public int getMovementGranularities() { 1715 if (Build.VERSION.SDK_INT >= 16) { 1716 return mInfo.getMovementGranularities(); 1717 } else { 1718 return 0; 1719 } 1720 } 1721 1722 /** 1723 * Finds {@link android.view.accessibility.AccessibilityNodeInfo}s by text. The match 1724 * is case insensitive containment. The search is relative to this info i.e. this 1725 * info is the root of the traversed tree. 1726 * <p> 1727 * <strong>Note:</strong> It is a client responsibility to recycle the 1728 * received info by calling {@link android.view.accessibility.AccessibilityNodeInfo#recycle()} 1729 * to avoid creating of multiple instances. 1730 * </p> 1731 * 1732 * @param text The searched text. 1733 * @return A list of node info. 1734 */ 1735 public List<AccessibilityNodeInfoCompat> findAccessibilityNodeInfosByText(String text) { 1736 List<AccessibilityNodeInfoCompat> result = new ArrayList<AccessibilityNodeInfoCompat>(); 1737 List<AccessibilityNodeInfo> infos = mInfo.findAccessibilityNodeInfosByText(text); 1738 final int infoCount = infos.size(); 1739 for (int i = 0; i < infoCount; i++) { 1740 AccessibilityNodeInfo info = infos.get(i); 1741 result.add(AccessibilityNodeInfoCompat.wrap(info)); 1742 } 1743 return result; 1744 } 1745 1746 /** 1747 * Gets the parent. 1748 * <p> 1749 * <strong>Note:</strong> It is a client responsibility to recycle the 1750 * received info by calling {@link android.view.accessibility.AccessibilityNodeInfo#recycle()} 1751 * to avoid creating of multiple instances. 1752 * </p> 1753 * 1754 * @return The parent. 1755 */ 1756 public AccessibilityNodeInfoCompat getParent() { 1757 return AccessibilityNodeInfoCompat.wrapNonNullInstance(mInfo.getParent()); 1758 } 1759 1760 /** 1761 * Sets the parent. 1762 * <p> 1763 * <strong>Note:</strong> Cannot be called from an 1764 * {@link android.accessibilityservice.AccessibilityService}. This class is 1765 * made immutable before being delivered to an AccessibilityService. 1766 * </p> 1767 * 1768 * @param parent The parent. 1769 * @throws IllegalStateException If called from an AccessibilityService. 1770 */ 1771 public void setParent(View parent) { 1772 mInfo.setParent(parent); 1773 } 1774 1775 /** 1776 * Sets the parent to be a virtual descendant of the given <code>root</code>. 1777 * If <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root 1778 * is set as the parent. 1779 * <p> 1780 * A virtual descendant is an imaginary View that is reported as a part of the view 1781 * hierarchy for accessibility purposes. This enables custom views that draw complex 1782 * content to report them selves as a tree of virtual views, thus conveying their 1783 * logical structure. 1784 * </p> 1785 * <p> 1786 * <strong>Note:</strong> Cannot be called from an 1787 * {@link android.accessibilityservice.AccessibilityService}. 1788 * This class is made immutable before being delivered to an AccessibilityService. 1789 * </p> 1790 * 1791 * @param root The root of the virtual subtree. 1792 * @param virtualDescendantId The id of the virtual descendant. 1793 */ 1794 public void setParent(View root, int virtualDescendantId) { 1795 mParentVirtualDescendantId = virtualDescendantId; 1796 if (Build.VERSION.SDK_INT >= 16) { 1797 mInfo.setParent(root, virtualDescendantId); 1798 } 1799 } 1800 1801 /** 1802 * Gets the node bounds in parent coordinates. 1803 * 1804 * @param outBounds The output node bounds. 1805 */ 1806 public void getBoundsInParent(Rect outBounds) { 1807 mInfo.getBoundsInParent(outBounds); 1808 } 1809 1810 /** 1811 * Sets the node bounds in parent coordinates. 1812 * <p> 1813 * <strong>Note:</strong> Cannot be called from an 1814 * {@link android.accessibilityservice.AccessibilityService}. This class is 1815 * made immutable before being delivered to an AccessibilityService. 1816 * </p> 1817 * 1818 * @param bounds The node bounds. 1819 * @throws IllegalStateException If called from an AccessibilityService. 1820 */ 1821 public void setBoundsInParent(Rect bounds) { 1822 mInfo.setBoundsInParent(bounds); 1823 } 1824 1825 /** 1826 * Gets the node bounds in screen coordinates. 1827 * 1828 * @param outBounds The output node bounds. 1829 */ 1830 public void getBoundsInScreen(Rect outBounds) { 1831 mInfo.getBoundsInScreen(outBounds); 1832 } 1833 1834 /** 1835 * Sets the node bounds in screen coordinates. 1836 * <p> 1837 * <strong>Note:</strong> Cannot be called from an 1838 * {@link android.accessibilityservice.AccessibilityService}. This class is 1839 * made immutable before being delivered to an AccessibilityService. 1840 * </p> 1841 * 1842 * @param bounds The node bounds. 1843 * @throws IllegalStateException If called from an AccessibilityService. 1844 */ 1845 public void setBoundsInScreen(Rect bounds) { 1846 mInfo.setBoundsInScreen(bounds); 1847 } 1848 1849 /** 1850 * Gets whether this node is checkable. 1851 * 1852 * @return True if the node is checkable. 1853 */ 1854 public boolean isCheckable() { 1855 return mInfo.isCheckable(); 1856 } 1857 1858 /** 1859 * Sets whether this node is checkable. 1860 * <p> 1861 * <strong>Note:</strong> Cannot be called from an 1862 * {@link android.accessibilityservice.AccessibilityService}. This class is 1863 * made immutable before being delivered to an AccessibilityService. 1864 * </p> 1865 * 1866 * @param checkable True if the node is checkable. 1867 * @throws IllegalStateException If called from an AccessibilityService. 1868 */ 1869 public void setCheckable(boolean checkable) { 1870 mInfo.setCheckable(checkable); 1871 } 1872 1873 /** 1874 * Gets whether this node is checked. 1875 * 1876 * @return True if the node is checked. 1877 */ 1878 public boolean isChecked() { 1879 return mInfo.isChecked(); 1880 } 1881 1882 /** 1883 * Sets whether this node is checked. 1884 * <p> 1885 * <strong>Note:</strong> Cannot be called from an 1886 * {@link android.accessibilityservice.AccessibilityService}. This class is 1887 * made immutable before being delivered to an AccessibilityService. 1888 * </p> 1889 * 1890 * @param checked True if the node is checked. 1891 * @throws IllegalStateException If called from an AccessibilityService. 1892 */ 1893 public void setChecked(boolean checked) { 1894 mInfo.setChecked(checked); 1895 } 1896 1897 /** 1898 * Gets whether this node is focusable. 1899 * 1900 * @return True if the node is focusable. 1901 */ 1902 public boolean isFocusable() { 1903 return mInfo.isFocusable(); 1904 } 1905 1906 /** 1907 * Sets whether this node is focusable. 1908 * <p> 1909 * <strong>Note:</strong> Cannot be called from an 1910 * {@link android.accessibilityservice.AccessibilityService}. This class is 1911 * made immutable before being delivered to an AccessibilityService. 1912 * </p> 1913 * 1914 * @param focusable True if the node is focusable. 1915 * @throws IllegalStateException If called from an AccessibilityService. 1916 */ 1917 public void setFocusable(boolean focusable) { 1918 mInfo.setFocusable(focusable); 1919 } 1920 1921 /** 1922 * Gets whether this node is focused. 1923 * 1924 * @return True if the node is focused. 1925 */ 1926 public boolean isFocused() { 1927 return mInfo.isFocused(); 1928 } 1929 1930 /** 1931 * Sets whether this node is focused. 1932 * <p> 1933 * <strong>Note:</strong> Cannot be called from an 1934 * {@link android.accessibilityservice.AccessibilityService}. This class is 1935 * made immutable before being delivered to an AccessibilityService. 1936 * </p> 1937 * 1938 * @param focused True if the node is focused. 1939 * @throws IllegalStateException If called from an AccessibilityService. 1940 */ 1941 public void setFocused(boolean focused) { 1942 mInfo.setFocused(focused); 1943 } 1944 1945 /** 1946 * Gets whether this node is visible to the user. 1947 * 1948 * @return Whether the node is visible to the user. 1949 */ 1950 public boolean isVisibleToUser() { 1951 if (Build.VERSION.SDK_INT >= 16) { 1952 return mInfo.isVisibleToUser(); 1953 } else { 1954 return false; 1955 } 1956 } 1957 1958 /** 1959 * Sets whether this node is visible to the user. 1960 * <p> 1961 * <strong>Note:</strong> Cannot be called from an 1962 * {@link android.accessibilityservice.AccessibilityService}. 1963 * This class is made immutable before being delivered to an AccessibilityService. 1964 * </p> 1965 * 1966 * @param visibleToUser Whether the node is visible to the user. 1967 * 1968 * @throws IllegalStateException If called from an AccessibilityService. 1969 */ 1970 public void setVisibleToUser(boolean visibleToUser) { 1971 if (Build.VERSION.SDK_INT >= 16) { 1972 mInfo.setVisibleToUser(visibleToUser); 1973 } 1974 } 1975 1976 /** 1977 * Gets whether this node is accessibility focused. 1978 * 1979 * @return True if the node is accessibility focused. 1980 */ 1981 public boolean isAccessibilityFocused() { 1982 if (Build.VERSION.SDK_INT >= 16) { 1983 return mInfo.isAccessibilityFocused(); 1984 } else { 1985 return false; 1986 } 1987 } 1988 1989 /** 1990 * Sets whether this node is accessibility focused. 1991 * <p> 1992 * <strong>Note:</strong> Cannot be called from an 1993 * {@link android.accessibilityservice.AccessibilityService}. 1994 * This class is made immutable before being delivered to an AccessibilityService. 1995 * </p> 1996 * 1997 * @param focused True if the node is accessibility focused. 1998 * 1999 * @throws IllegalStateException If called from an AccessibilityService. 2000 */ 2001 public void setAccessibilityFocused(boolean focused) { 2002 if (Build.VERSION.SDK_INT >= 16) { 2003 mInfo.setAccessibilityFocused(focused); 2004 } 2005 } 2006 2007 /** 2008 * Gets whether this node is selected. 2009 * 2010 * @return True if the node is selected. 2011 */ 2012 public boolean isSelected() { 2013 return mInfo.isSelected(); 2014 } 2015 2016 /** 2017 * Sets whether this node is selected. 2018 * <p> 2019 * <strong>Note:</strong> Cannot be called from an 2020 * {@link android.accessibilityservice.AccessibilityService}. This class is 2021 * made immutable before being delivered to an AccessibilityService. 2022 * </p> 2023 * 2024 * @param selected True if the node is selected. 2025 * @throws IllegalStateException If called from an AccessibilityService. 2026 */ 2027 public void setSelected(boolean selected) { 2028 mInfo.setSelected(selected); 2029 } 2030 2031 /** 2032 * Gets whether this node is clickable. 2033 * 2034 * @return True if the node is clickable. 2035 */ 2036 public boolean isClickable() { 2037 return mInfo.isClickable(); 2038 } 2039 2040 /** 2041 * Sets whether this node is clickable. 2042 * <p> 2043 * <strong>Note:</strong> Cannot be called from an 2044 * {@link android.accessibilityservice.AccessibilityService}. This class is 2045 * made immutable before being delivered to an AccessibilityService. 2046 * </p> 2047 * 2048 * @param clickable True if the node is clickable. 2049 * @throws IllegalStateException If called from an AccessibilityService. 2050 */ 2051 public void setClickable(boolean clickable) { 2052 mInfo.setClickable(clickable); 2053 } 2054 2055 /** 2056 * Gets whether this node is long clickable. 2057 * 2058 * @return True if the node is long clickable. 2059 */ 2060 public boolean isLongClickable() { 2061 return mInfo.isLongClickable(); 2062 } 2063 2064 /** 2065 * Sets whether this node is long clickable. 2066 * <p> 2067 * <strong>Note:</strong> Cannot be called from an 2068 * {@link android.accessibilityservice.AccessibilityService}. This class is 2069 * made immutable before being delivered to an AccessibilityService. 2070 * </p> 2071 * 2072 * @param longClickable True if the node is long clickable. 2073 * @throws IllegalStateException If called from an AccessibilityService. 2074 */ 2075 public void setLongClickable(boolean longClickable) { 2076 mInfo.setLongClickable(longClickable); 2077 } 2078 2079 /** 2080 * Gets whether this node is enabled. 2081 * 2082 * @return True if the node is enabled. 2083 */ 2084 public boolean isEnabled() { 2085 return mInfo.isEnabled(); 2086 } 2087 2088 /** 2089 * Sets whether this node is enabled. 2090 * <p> 2091 * <strong>Note:</strong> Cannot be called from an 2092 * {@link android.accessibilityservice.AccessibilityService}. This class is 2093 * made immutable before being delivered to an AccessibilityService. 2094 * </p> 2095 * 2096 * @param enabled True if the node is enabled. 2097 * @throws IllegalStateException If called from an AccessibilityService. 2098 */ 2099 public void setEnabled(boolean enabled) { 2100 mInfo.setEnabled(enabled); 2101 } 2102 2103 /** 2104 * Gets whether this node is a password. 2105 * 2106 * @return True if the node is a password. 2107 */ 2108 public boolean isPassword() { 2109 return mInfo.isPassword(); 2110 } 2111 2112 /** 2113 * Sets whether this node is a password. 2114 * <p> 2115 * <strong>Note:</strong> Cannot be called from an 2116 * {@link android.accessibilityservice.AccessibilityService}. This class is 2117 * made immutable before being delivered to an AccessibilityService. 2118 * </p> 2119 * 2120 * @param password True if the node is a password. 2121 * @throws IllegalStateException If called from an AccessibilityService. 2122 */ 2123 public void setPassword(boolean password) { 2124 mInfo.setPassword(password); 2125 } 2126 2127 /** 2128 * Gets if the node is scrollable. 2129 * 2130 * @return True if the node is scrollable, false otherwise. 2131 */ 2132 public boolean isScrollable() { 2133 return mInfo.isScrollable(); 2134 } 2135 2136 /** 2137 * Sets if the node is scrollable. 2138 * <p> 2139 * <strong>Note:</strong> Cannot be called from an 2140 * {@link android.accessibilityservice.AccessibilityService}. This class is 2141 * made immutable before being delivered to an AccessibilityService. 2142 * </p> 2143 * 2144 * @param scrollable True if the node is scrollable, false otherwise. 2145 * @throws IllegalStateException If called from an AccessibilityService. 2146 */ 2147 public void setScrollable(boolean scrollable) { 2148 mInfo.setScrollable(scrollable); 2149 } 2150 2151 /** 2152 * Returns whether the node originates from a view considered important for accessibility. 2153 * 2154 * @return {@code true} if the node originates from a view considered important for 2155 * accessibility, {@code false} otherwise 2156 * 2157 * @see View#isImportantForAccessibility() 2158 */ 2159 public boolean isImportantForAccessibility() { 2160 if (Build.VERSION.SDK_INT >= 24) { 2161 return mInfo.isImportantForAccessibility(); 2162 } else { 2163 return true; 2164 } 2165 } 2166 2167 /** 2168 * Sets whether the node is considered important for accessibility. 2169 * <p> 2170 * <strong>Note:</strong> Cannot be called from an 2171 * {@link android.accessibilityservice.AccessibilityService}. 2172 * This class is made immutable before being delivered to an AccessibilityService. 2173 * </p> 2174 * 2175 * @param important {@code true} if the node is considered important for accessibility, 2176 * {@code false} otherwise 2177 */ 2178 public void setImportantForAccessibility(boolean important) { 2179 if (Build.VERSION.SDK_INT >= 24) { 2180 mInfo.setImportantForAccessibility(important); 2181 } 2182 } 2183 2184 /** 2185 * Gets the package this node comes from. 2186 * 2187 * @return The package name. 2188 */ 2189 public CharSequence getPackageName() { 2190 return mInfo.getPackageName(); 2191 } 2192 2193 /** 2194 * Sets the package this node comes from. 2195 * <p> 2196 * <strong>Note:</strong> Cannot be called from an 2197 * {@link android.accessibilityservice.AccessibilityService}. This class is 2198 * made immutable before being delivered to an AccessibilityService. 2199 * </p> 2200 * 2201 * @param packageName The package name. 2202 * @throws IllegalStateException If called from an AccessibilityService. 2203 */ 2204 public void setPackageName(CharSequence packageName) { 2205 mInfo.setPackageName(packageName); 2206 } 2207 2208 /** 2209 * Gets the class this node comes from. 2210 * 2211 * @return The class name. 2212 */ 2213 public CharSequence getClassName() { 2214 return mInfo.getClassName(); 2215 } 2216 2217 /** 2218 * Sets the class this node comes from. 2219 * <p> 2220 * <strong>Note:</strong> Cannot be called from an 2221 * {@link android.accessibilityservice.AccessibilityService}. This class is 2222 * made immutable before being delivered to an AccessibilityService. 2223 * </p> 2224 * 2225 * @param className The class name. 2226 * @throws IllegalStateException If called from an AccessibilityService. 2227 */ 2228 public void setClassName(CharSequence className) { 2229 mInfo.setClassName(className); 2230 } 2231 2232 /** 2233 * Gets the text of this node. 2234 * 2235 * @return The text. 2236 */ 2237 public CharSequence getText() { 2238 return mInfo.getText(); 2239 } 2240 2241 /** 2242 * Sets the text of this node. 2243 * <p> 2244 * <strong>Note:</strong> Cannot be called from an 2245 * {@link android.accessibilityservice.AccessibilityService}. This class is 2246 * made immutable before being delivered to an AccessibilityService. 2247 * </p> 2248 * 2249 * @param text The text. 2250 * @throws IllegalStateException If called from an AccessibilityService. 2251 */ 2252 public void setText(CharSequence text) { 2253 mInfo.setText(text); 2254 } 2255 2256 /** 2257 * Gets the content description of this node. 2258 * 2259 * @return The content description. 2260 */ 2261 public CharSequence getContentDescription() { 2262 return mInfo.getContentDescription(); 2263 } 2264 2265 /** 2266 * Sets the content description of this node. 2267 * <p> 2268 * <strong>Note:</strong> Cannot be called from an 2269 * {@link android.accessibilityservice.AccessibilityService}. This class is 2270 * made immutable before being delivered to an AccessibilityService. 2271 * </p> 2272 * 2273 * @param contentDescription The content description. 2274 * @throws IllegalStateException If called from an AccessibilityService. 2275 */ 2276 public void setContentDescription(CharSequence contentDescription) { 2277 mInfo.setContentDescription(contentDescription); 2278 } 2279 2280 /** 2281 * Return an instance back to be reused. 2282 * <p> 2283 * <strong>Note:</strong> You must not touch the object after calling this function. 2284 * 2285 * @throws IllegalStateException If the info is already recycled. 2286 */ 2287 public void recycle() { 2288 mInfo.recycle(); 2289 } 2290 2291 /** 2292 * Sets the fully qualified resource name of the source view's id. 2293 * 2294 * <p> 2295 * <strong>Note:</strong> Cannot be called from an 2296 * {@link android.accessibilityservice.AccessibilityService}. 2297 * This class is made immutable before being delivered to an AccessibilityService. 2298 * </p> 2299 * 2300 * @param viewId The id resource name. 2301 */ 2302 public void setViewIdResourceName(String viewId) { 2303 if (Build.VERSION.SDK_INT >= 18) { 2304 mInfo.setViewIdResourceName(viewId); 2305 } 2306 } 2307 2308 /** 2309 * Gets the fully qualified resource name of the source view's id. 2310 * 2311 * <p> 2312 * <strong>Note:</strong> The primary usage of this API is for UI test automation 2313 * and in order to report the source view id of an {@link AccessibilityNodeInfoCompat} 2314 * the client has to set the {@link AccessibilityServiceInfoCompat#FLAG_REPORT_VIEW_IDS} 2315 * flag when configuring his {@link android.accessibilityservice.AccessibilityService}. 2316 * </p> 2317 * 2318 * @return The id resource name. 2319 */ 2320 public String getViewIdResourceName() { 2321 if (Build.VERSION.SDK_INT >= 18) { 2322 return mInfo.getViewIdResourceName(); 2323 } else { 2324 return null; 2325 } 2326 } 2327 2328 /** 2329 * Gets the node's live region mode. 2330 * <p> 2331 * A live region is a node that contains information that is important for 2332 * the user and when it changes the user should be notified. For example, 2333 * in a login screen with a TextView that displays an "incorrect password" 2334 * notification, that view should be marked as a live region with mode 2335 * {@link ViewCompat#ACCESSIBILITY_LIVE_REGION_POLITE}. 2336 * <p> 2337 * It is the responsibility of the accessibility service to monitor 2338 * {@link AccessibilityEventCompat#TYPE_WINDOW_CONTENT_CHANGED} events 2339 * indicating changes to live region nodes and their children. 2340 * 2341 * @return The live region mode, or 2342 * {@link ViewCompat#ACCESSIBILITY_LIVE_REGION_NONE} if the view is 2343 * not a live region. 2344 * @see ViewCompat#getAccessibilityLiveRegion(View) 2345 */ 2346 public int getLiveRegion() { 2347 if (Build.VERSION.SDK_INT >= 19) { 2348 return mInfo.getLiveRegion(); 2349 } else { 2350 return ViewCompat.ACCESSIBILITY_LIVE_REGION_NONE; 2351 } 2352 } 2353 2354 /** 2355 * Sets the node's live region mode. 2356 * <p> 2357 * <strong>Note:</strong> Cannot be called from an 2358 * {@link android.accessibilityservice.AccessibilityService}. This class is 2359 * made immutable before being delivered to an AccessibilityService. 2360 * 2361 * @param mode The live region mode, or 2362 * {@link ViewCompat#ACCESSIBILITY_LIVE_REGION_NONE} if the view is 2363 * not a live region. 2364 * @see ViewCompat#setAccessibilityLiveRegion(View, int) 2365 */ 2366 public void setLiveRegion(int mode) { 2367 if (Build.VERSION.SDK_INT >= 19) { 2368 mInfo.setLiveRegion(mode); 2369 } 2370 } 2371 2372 /** 2373 * Get the drawing order of the view corresponding it this node. 2374 * <p> 2375 * Drawing order is determined only within the node's parent, so this index is only relative 2376 * to its siblings. 2377 * <p> 2378 * In some cases, the drawing order is essentially simultaneous, so it is possible for two 2379 * siblings to return the same value. It is also possible that values will be skipped. 2380 * 2381 * @return The drawing position of the view corresponding to this node relative to its siblings. 2382 */ 2383 public int getDrawingOrder() { 2384 if (Build.VERSION.SDK_INT >= 24) { 2385 return mInfo.getDrawingOrder(); 2386 } else { 2387 return 0; 2388 } 2389 } 2390 2391 /** 2392 * Set the drawing order of the view corresponding it this node. 2393 * 2394 * <p> 2395 * <strong>Note:</strong> Cannot be called from an 2396 * {@link android.accessibilityservice.AccessibilityService}. 2397 * This class is made immutable before being delivered to an AccessibilityService. 2398 * </p> 2399 * @param drawingOrderInParent 2400 * @throws IllegalStateException If called from an AccessibilityService. 2401 */ 2402 public void setDrawingOrder(int drawingOrderInParent) { 2403 if (Build.VERSION.SDK_INT >= 24) { 2404 mInfo.setDrawingOrder(drawingOrderInParent); 2405 } 2406 } 2407 2408 /** 2409 * Gets the collection info if the node is a collection. A collection 2410 * child is always a collection item. 2411 * 2412 * @return The collection info. 2413 */ 2414 public CollectionInfoCompat getCollectionInfo() { 2415 if (Build.VERSION.SDK_INT >= 19) { 2416 AccessibilityNodeInfo.CollectionInfo info = mInfo.getCollectionInfo(); 2417 if (info != null) { 2418 return new CollectionInfoCompat(info); 2419 } 2420 } 2421 return null; 2422 } 2423 2424 public void setCollectionInfo(Object collectionInfo) { 2425 if (Build.VERSION.SDK_INT >= 19) { 2426 mInfo.setCollectionInfo((collectionInfo == null) ? null 2427 : (AccessibilityNodeInfo.CollectionInfo) ((CollectionInfoCompat) 2428 collectionInfo).mInfo); 2429 } 2430 2431 } 2432 2433 public void setCollectionItemInfo(Object collectionItemInfo) { 2434 if (Build.VERSION.SDK_INT >= 19) { 2435 mInfo.setCollectionItemInfo((collectionItemInfo == null) ? null 2436 : (AccessibilityNodeInfo.CollectionItemInfo) ((CollectionItemInfoCompat) 2437 collectionItemInfo).mInfo); 2438 } 2439 } 2440 2441 /** 2442 * Gets the collection item info if the node is a collection item. A collection 2443 * item is always a child of a collection. 2444 * 2445 * @return The collection item info. 2446 */ 2447 public CollectionItemInfoCompat getCollectionItemInfo() { 2448 if (Build.VERSION.SDK_INT >= 19) { 2449 AccessibilityNodeInfo.CollectionItemInfo info = mInfo.getCollectionItemInfo(); 2450 if (info != null) { 2451 return new CollectionItemInfoCompat(info); 2452 } 2453 } 2454 return null; 2455 } 2456 2457 /** 2458 * Gets the range info if this node is a range. 2459 * 2460 * @return The range. 2461 */ 2462 public RangeInfoCompat getRangeInfo() { 2463 if (Build.VERSION.SDK_INT >= 19) { 2464 AccessibilityNodeInfo.RangeInfo info = mInfo.getRangeInfo(); 2465 if (info != null) { 2466 return new RangeInfoCompat(info); 2467 } 2468 } 2469 return null; 2470 } 2471 2472 /** 2473 * Sets the range info if this node is a range. 2474 * <p> 2475 * <strong>Note:</strong> Cannot be called from an 2476 * {@link android.accessibilityservice.AccessibilityService}. 2477 * This class is made immutable before being delivered to an AccessibilityService. 2478 * </p> 2479 * 2480 * @param rangeInfo The range info. 2481 */ 2482 public void setRangeInfo(RangeInfoCompat rangeInfo) { 2483 if (Build.VERSION.SDK_INT >= 19) { 2484 mInfo.setRangeInfo((AccessibilityNodeInfo.RangeInfo) rangeInfo.mInfo); 2485 } 2486 } 2487 2488 /** 2489 * Gets the actions that can be performed on the node. 2490 * 2491 * @return A list of AccessibilityActions. 2492 */ 2493 @SuppressWarnings("unchecked") 2494 public List<AccessibilityActionCompat> getActionList() { 2495 List<Object> actions = null; 2496 if (Build.VERSION.SDK_INT >= 21) { 2497 actions = (List<Object>) (List<?>) mInfo.getActionList(); 2498 } 2499 if (actions != null) { 2500 List<AccessibilityActionCompat> result = new ArrayList<AccessibilityActionCompat>(); 2501 final int actionCount = actions.size(); 2502 for (int i = 0; i < actionCount; i++) { 2503 Object action = actions.get(i); 2504 result.add(new AccessibilityActionCompat(action)); 2505 } 2506 return result; 2507 } else { 2508 return Collections.<AccessibilityActionCompat>emptyList(); 2509 } 2510 } 2511 2512 /** 2513 * Sets if the content of this node is invalid. For example, 2514 * a date is not well-formed. 2515 * <p> 2516 * <strong>Note:</strong> Cannot be called from an 2517 * {@link android.accessibilityservice.AccessibilityService}. 2518 * This class is made immutable before being delivered to an AccessibilityService. 2519 * </p> 2520 * 2521 * @param contentInvalid If the node content is invalid. 2522 */ 2523 public void setContentInvalid(boolean contentInvalid) { 2524 if (Build.VERSION.SDK_INT >= 19) { 2525 mInfo.setContentInvalid(contentInvalid); 2526 } 2527 } 2528 2529 /** 2530 * Gets if the content of this node is invalid. For example, 2531 * a date is not well-formed. 2532 * 2533 * @return If the node content is invalid. 2534 */ 2535 public boolean isContentInvalid() { 2536 if (Build.VERSION.SDK_INT >= 19) { 2537 return mInfo.isContentInvalid(); 2538 } else { 2539 return false; 2540 } 2541 } 2542 2543 /** 2544 * Gets whether this node is context clickable. 2545 * 2546 * @return True if the node is context clickable. 2547 */ 2548 public boolean isContextClickable() { 2549 if (Build.VERSION.SDK_INT >= 23) { 2550 return mInfo.isContextClickable(); 2551 } else { 2552 return false; 2553 } 2554 } 2555 2556 /** 2557 * Sets whether this node is context clickable. 2558 * <p> 2559 * <strong>Note:</strong> Cannot be called from an 2560 * {@link android.accessibilityservice.AccessibilityService}. This class is made immutable 2561 * before being delivered to an AccessibilityService. 2562 * </p> 2563 * 2564 * @param contextClickable True if the node is context clickable. 2565 * @throws IllegalStateException If called from an AccessibilityService. 2566 */ 2567 public void setContextClickable(boolean contextClickable) { 2568 if (Build.VERSION.SDK_INT >= 23) { 2569 mInfo.setContextClickable(contextClickable); 2570 } 2571 } 2572 2573 /** 2574 * Gets the hint text of this node. Only applies to nodes where text can be entered. 2575 * 2576 * @return The hint text. 2577 */ 2578 public @Nullable CharSequence getHintText() { 2579 if (Build.VERSION.SDK_INT >= 26) { 2580 return mInfo.getHintText(); 2581 } else if (Build.VERSION.SDK_INT >= 19) { 2582 return mInfo.getExtras().getCharSequence(HINT_TEXT_KEY); 2583 } 2584 return null; 2585 } 2586 2587 /** 2588 * Sets the hint text of this node. Only applies to nodes where text can be entered. 2589 * <p>This method has no effect below API 19</p> 2590 * <p> 2591 * <strong>Note:</strong> Cannot be called from an 2592 * {@link android.accessibilityservice.AccessibilityService}. 2593 * This class is made immutable before being delivered to an AccessibilityService. 2594 * </p> 2595 * 2596 * @param hintText The hint text for this mode. 2597 * 2598 * @throws IllegalStateException If called from an AccessibilityService. 2599 */ 2600 public void setHintText(@Nullable CharSequence hintText) { 2601 if (Build.VERSION.SDK_INT >= 26) { 2602 mInfo.setHintText(hintText); 2603 } else if (Build.VERSION.SDK_INT >= 19) { 2604 mInfo.getExtras().putCharSequence(HINT_TEXT_KEY, hintText); 2605 } 2606 } 2607 2608 2609 /** 2610 * Sets the error text of this node. 2611 * <p> 2612 * <strong>Note:</strong> Cannot be called from an 2613 * {@link android.accessibilityservice.AccessibilityService}. 2614 * This class is made immutable before being delivered to an AccessibilityService. 2615 * </p> 2616 * 2617 * @param error The error text. 2618 * 2619 * @throws IllegalStateException If called from an AccessibilityService. 2620 */ 2621 public void setError(CharSequence error) { 2622 if (Build.VERSION.SDK_INT >= 21) { 2623 mInfo.setError(error); 2624 } 2625 } 2626 2627 /** 2628 * Gets the error text of this node. 2629 * 2630 * @return The error text. 2631 */ 2632 public CharSequence getError() { 2633 if (Build.VERSION.SDK_INT >= 21) { 2634 return mInfo.getError(); 2635 } else { 2636 return null; 2637 } 2638 } 2639 2640 /** 2641 * Sets the view for which the view represented by this info serves as a 2642 * label for accessibility purposes. 2643 * 2644 * @param labeled The view for which this info serves as a label. 2645 */ 2646 public void setLabelFor(View labeled) { 2647 if (Build.VERSION.SDK_INT >= 17) { 2648 mInfo.setLabelFor(labeled); 2649 } 2650 } 2651 2652 /** 2653 * Sets the view for which the view represented by this info serves as a 2654 * label for accessibility purposes. If <code>virtualDescendantId</code> 2655 * is {@link View#NO_ID} the root is set as the labeled. 2656 * <p> 2657 * A virtual descendant is an imaginary View that is reported as a part of the view 2658 * hierarchy for accessibility purposes. This enables custom views that draw complex 2659 * content to report themselves as a tree of virtual views, thus conveying their 2660 * logical structure. 2661 * </p> 2662 * 2663 * @param root The root whose virtual descendant serves as a label. 2664 * @param virtualDescendantId The id of the virtual descendant. 2665 */ 2666 public void setLabelFor(View root, int virtualDescendantId) { 2667 if (Build.VERSION.SDK_INT >= 17) { 2668 mInfo.setLabelFor(root, virtualDescendantId); 2669 } 2670 } 2671 2672 /** 2673 * Gets the node info for which the view represented by this info serves as 2674 * a label for accessibility purposes. 2675 * <p> 2676 * <strong>Note:</strong> It is a client responsibility to recycle the 2677 * received info by calling {@link AccessibilityNodeInfoCompat#recycle()} 2678 * to avoid creating of multiple instances. 2679 * </p> 2680 * 2681 * @return The labeled info. 2682 */ 2683 public AccessibilityNodeInfoCompat getLabelFor() { 2684 if (Build.VERSION.SDK_INT >= 17) { 2685 return AccessibilityNodeInfoCompat.wrapNonNullInstance(mInfo.getLabelFor()); 2686 } else { 2687 return null; 2688 } 2689 } 2690 2691 /** 2692 * Sets the view which serves as the label of the view represented by 2693 * this info for accessibility purposes. 2694 * 2695 * @param label The view that labels this node's source. 2696 */ 2697 public void setLabeledBy(View label) { 2698 if (Build.VERSION.SDK_INT >= 17) { 2699 mInfo.setLabeledBy(label); 2700 } 2701 } 2702 2703 /** 2704 * Sets the view which serves as the label of the view represented by 2705 * this info for accessibility purposes. If <code>virtualDescendantId</code> 2706 * is {@link View#NO_ID} the root is set as the label. 2707 * <p> 2708 * A virtual descendant is an imaginary View that is reported as a part of the view 2709 * hierarchy for accessibility purposes. This enables custom views that draw complex 2710 * content to report themselves as a tree of virtual views, thus conveying their 2711 * logical structure. 2712 * </p> 2713 * <p> 2714 * <strong>Note:</strong> Cannot be called from an 2715 * {@link android.accessibilityservice.AccessibilityService}. 2716 * This class is made immutable before being delivered to an AccessibilityService. 2717 * </p> 2718 * 2719 * @param root The root whose virtual descendant labels this node's source. 2720 * @param virtualDescendantId The id of the virtual descendant. 2721 */ 2722 public void setLabeledBy(View root, int virtualDescendantId) { 2723 if (Build.VERSION.SDK_INT >= 17) { 2724 mInfo.setLabeledBy(root, virtualDescendantId); 2725 } 2726 } 2727 2728 /** 2729 * Gets the node info which serves as the label of the view represented by 2730 * this info for accessibility purposes. 2731 * <p> 2732 * <strong>Note:</strong> It is a client responsibility to recycle the 2733 * received info by calling {@link AccessibilityNodeInfoCompat#recycle()} 2734 * to avoid creating of multiple instances. 2735 * </p> 2736 * 2737 * @return The label. 2738 */ 2739 public AccessibilityNodeInfoCompat getLabeledBy() { 2740 if (Build.VERSION.SDK_INT >= 17) { 2741 return AccessibilityNodeInfoCompat.wrapNonNullInstance(mInfo.getLabeledBy()); 2742 } else { 2743 return null; 2744 } 2745 } 2746 2747 /** 2748 * Gets if this node opens a popup or a dialog. 2749 * 2750 * @return If the the node opens a popup. 2751 */ 2752 public boolean canOpenPopup() { 2753 if (Build.VERSION.SDK_INT >= 19) { 2754 return mInfo.canOpenPopup(); 2755 } else { 2756 return false; 2757 } 2758 } 2759 2760 /** 2761 * Sets if this node opens a popup or a dialog. 2762 * <p> 2763 * <strong>Note:</strong> Cannot be called from an 2764 * {@link android.accessibilityservice.AccessibilityService}. 2765 * This class is made immutable before being delivered to an AccessibilityService. 2766 * </p> 2767 * 2768 * @param opensPopup If the the node opens a popup. 2769 */ 2770 public void setCanOpenPopup(boolean opensPopup) { 2771 if (Build.VERSION.SDK_INT >= 19) { 2772 mInfo.setCanOpenPopup(opensPopup); 2773 } 2774 } 2775 2776 /** 2777 * Finds {@link AccessibilityNodeInfoCompat}s by the fully qualified view id's resource 2778 * name where a fully qualified id is of the from "package:id/id_resource_name". 2779 * For example, if the target application's package is "foo.bar" and the id 2780 * resource name is "baz", the fully qualified resource id is "foo.bar:id/baz". 2781 * 2782 * <p> 2783 * <strong>Note:</strong> It is a client responsibility to recycle the 2784 * received info by calling {@link AccessibilityNodeInfoCompat#recycle()} 2785 * to avoid creating of multiple instances. 2786 * </p> 2787 * <p> 2788 * <strong>Note:</strong> The primary usage of this API is for UI test automation 2789 * and in order to report the fully qualified view id if an 2790 * {@link AccessibilityNodeInfoCompat} the client has to set the 2791 * {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS} 2792 * flag when configuring his {@link android.accessibilityservice.AccessibilityService}. 2793 * </p> 2794 * 2795 * @param viewId The fully qualified resource name of the view id to find. 2796 * @return A list of node info. 2797 */ 2798 public List<AccessibilityNodeInfoCompat> findAccessibilityNodeInfosByViewId(String viewId) { 2799 if (Build.VERSION.SDK_INT >= 18) { 2800 List<AccessibilityNodeInfo> nodes = mInfo.findAccessibilityNodeInfosByViewId(viewId); 2801 List<AccessibilityNodeInfoCompat> result = new ArrayList<>(); 2802 for (AccessibilityNodeInfo node : nodes) { 2803 result.add(AccessibilityNodeInfoCompat.wrap(node)); 2804 } 2805 return result; 2806 } else { 2807 return Collections.emptyList(); 2808 } 2809 } 2810 2811 /** 2812 * Gets an optional bundle with extra data. The bundle 2813 * is lazily created and never <code>null</code>. 2814 * <p> 2815 * <strong>Note:</strong> It is recommended to use the package 2816 * name of your application as a prefix for the keys to avoid 2817 * collisions which may confuse an accessibility service if the 2818 * same key has different meaning when emitted from different 2819 * applications. 2820 * </p> 2821 * 2822 * @return The bundle. 2823 */ 2824 public Bundle getExtras() { 2825 if (Build.VERSION.SDK_INT >= 19) { 2826 return mInfo.getExtras(); 2827 } else { 2828 return new Bundle(); 2829 } 2830 } 2831 2832 /** 2833 * Gets the input type of the source as defined by {@link InputType}. 2834 * 2835 * @return The input type. 2836 */ 2837 public int getInputType() { 2838 if (Build.VERSION.SDK_INT >= 19) { 2839 return mInfo.getInputType(); 2840 } else { 2841 return InputType.TYPE_NULL; 2842 } 2843 } 2844 2845 /** 2846 * Sets the input type of the source as defined by {@link InputType}. 2847 * <p> 2848 * <strong>Note:</strong> Cannot be called from an 2849 * {@link android.accessibilityservice.AccessibilityService}. 2850 * This class is made immutable before being delivered to an 2851 * AccessibilityService. 2852 * </p> 2853 * 2854 * @param inputType The input type. 2855 * 2856 * @throws IllegalStateException If called from an AccessibilityService. 2857 */ 2858 public void setInputType(int inputType) { 2859 if (Build.VERSION.SDK_INT >= 19) { 2860 mInfo.setInputType(inputType); 2861 } 2862 } 2863 2864 /** 2865 * Sets the maximum text length, or -1 for no limit. 2866 * <p> 2867 * Typically used to indicate that an editable text field has a limit on 2868 * the number of characters entered. 2869 * <p> 2870 * <strong>Note:</strong> Cannot be called from an 2871 * {@link android.accessibilityservice.AccessibilityService}. 2872 * This class is made immutable before being delivered to an AccessibilityService. 2873 * 2874 * @param max The maximum text length. 2875 * @see #getMaxTextLength() 2876 * 2877 * @throws IllegalStateException If called from an AccessibilityService. 2878 */ 2879 public void setMaxTextLength(int max) { 2880 if (Build.VERSION.SDK_INT >= 21) { 2881 mInfo.setMaxTextLength(max); 2882 } 2883 } 2884 2885 /** 2886 * Returns the maximum text length for this node. 2887 * 2888 * @return The maximum text length, or -1 for no limit. 2889 * @see #setMaxTextLength(int) 2890 */ 2891 public int getMaxTextLength() { 2892 if (Build.VERSION.SDK_INT >= 21) { 2893 return mInfo.getMaxTextLength(); 2894 } else { 2895 return -1; 2896 } 2897 } 2898 2899 /** 2900 * Sets the text selection start and end. 2901 * <p> 2902 * <strong>Note:</strong> Cannot be called from an 2903 * {@link android.accessibilityservice.AccessibilityService}. 2904 * This class is made immutable before being delivered to an AccessibilityService. 2905 * </p> 2906 * 2907 * @param start The text selection start. 2908 * @param end The text selection end. 2909 * 2910 * @throws IllegalStateException If called from an AccessibilityService. 2911 */ 2912 public void setTextSelection(int start, int end) { 2913 if (Build.VERSION.SDK_INT >= 18) { 2914 mInfo.setTextSelection(start, end); 2915 } 2916 } 2917 2918 /** 2919 * Gets the text selection start. 2920 * 2921 * @return The text selection start if there is selection or -1. 2922 */ 2923 public int getTextSelectionStart() { 2924 if (Build.VERSION.SDK_INT >= 18) { 2925 return mInfo.getTextSelectionStart(); 2926 } else { 2927 return -1; 2928 } 2929 } 2930 2931 /** 2932 * Gets the text selection end. 2933 * 2934 * @return The text selection end if there is selection or -1. 2935 */ 2936 public int getTextSelectionEnd() { 2937 if (Build.VERSION.SDK_INT >= 18) { 2938 return mInfo.getTextSelectionEnd(); 2939 } else { 2940 return -1; 2941 } 2942 } 2943 2944 /** 2945 * Gets the node before which this one is visited during traversal. A screen-reader 2946 * must visit the content of this node before the content of the one it precedes. 2947 * 2948 * @return The succeeding node if such or <code>null</code>. 2949 * 2950 * @see #setTraversalBefore(android.view.View) 2951 * @see #setTraversalBefore(android.view.View, int) 2952 */ 2953 public AccessibilityNodeInfoCompat getTraversalBefore() { 2954 if (Build.VERSION.SDK_INT >= 22) { 2955 return AccessibilityNodeInfoCompat.wrapNonNullInstance(mInfo.getTraversalBefore()); 2956 } else { 2957 return null; 2958 } 2959 } 2960 2961 /** 2962 * Sets the view before whose node this one should be visited during traversal. A 2963 * screen-reader must visit the content of this node before the content of the one 2964 * it precedes. 2965 * <p> 2966 * <strong>Note:</strong> Cannot be called from an 2967 * {@link android.accessibilityservice.AccessibilityService}. 2968 * This class is made immutable before being delivered to an AccessibilityService. 2969 * </p> 2970 * 2971 * @param view The view providing the preceding node. 2972 * 2973 * @see #getTraversalBefore() 2974 */ 2975 public void setTraversalBefore(View view) { 2976 if (Build.VERSION.SDK_INT >= 22) { 2977 mInfo.setTraversalBefore(view); 2978 } 2979 } 2980 2981 /** 2982 * Sets the node before which this one is visited during traversal. A screen-reader 2983 * must visit the content of this node before the content of the one it precedes. 2984 * The successor is a virtual descendant of the given <code>root</code>. If 2985 * <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root is set 2986 * as the successor. 2987 * <p> 2988 * A virtual descendant is an imaginary View that is reported as a part of the view 2989 * hierarchy for accessibility purposes. This enables custom views that draw complex 2990 * content to report them selves as a tree of virtual views, thus conveying their 2991 * logical structure. 2992 * </p> 2993 * <p> 2994 * <strong>Note:</strong> Cannot be called from an 2995 * {@link android.accessibilityservice.AccessibilityService}. 2996 * This class is made immutable before being delivered to an AccessibilityService. 2997 * </p> 2998 * 2999 * @param root The root of the virtual subtree. 3000 * @param virtualDescendantId The id of the virtual descendant. 3001 */ 3002 public void setTraversalBefore(View root, int virtualDescendantId) { 3003 if (Build.VERSION.SDK_INT >= 22) { 3004 mInfo.setTraversalBefore(root, virtualDescendantId); 3005 } 3006 } 3007 3008 /** 3009 * Gets the node after which this one is visited in accessibility traversal. 3010 * A screen-reader must visit the content of the other node before the content 3011 * of this one. 3012 * 3013 * @return The succeeding node if such or <code>null</code>. 3014 * 3015 * @see #setTraversalAfter(android.view.View) 3016 * @see #setTraversalAfter(android.view.View, int) 3017 */ 3018 public AccessibilityNodeInfoCompat getTraversalAfter() { 3019 if (Build.VERSION.SDK_INT >= 22) { 3020 return AccessibilityNodeInfoCompat.wrapNonNullInstance(mInfo.getTraversalAfter()); 3021 } else { 3022 return null; 3023 } 3024 } 3025 3026 /** 3027 * Sets the view whose node is visited after this one in accessibility traversal. 3028 * A screen-reader must visit the content of the other node before the content 3029 * of this one. 3030 * <p> 3031 * <strong>Note:</strong> Cannot be called from an 3032 * {@link android.accessibilityservice.AccessibilityService}. 3033 * This class is made immutable before being delivered to an AccessibilityService. 3034 * </p> 3035 * 3036 * @param view The previous view. 3037 * 3038 * @see #getTraversalAfter() 3039 */ 3040 public void setTraversalAfter(View view) { 3041 if (Build.VERSION.SDK_INT >= 22) { 3042 mInfo.setTraversalAfter(view); 3043 } 3044 } 3045 3046 /** 3047 * Sets the node after which this one is visited in accessibility traversal. 3048 * A screen-reader must visit the content of the other node before the content 3049 * of this one. If <code>virtualDescendantId</code> equals to {@link View#NO_ID} 3050 * the root is set as the predecessor. 3051 * <p> 3052 * A virtual descendant is an imaginary View that is reported as a part of the view 3053 * hierarchy for accessibility purposes. This enables custom views that draw complex 3054 * content to report them selves as a tree of virtual views, thus conveying their 3055 * logical structure. 3056 * </p> 3057 * <p> 3058 * <strong>Note:</strong> Cannot be called from an 3059 * {@link android.accessibilityservice.AccessibilityService}. 3060 * This class is made immutable before being delivered to an AccessibilityService. 3061 * </p> 3062 * 3063 * @param root The root of the virtual subtree. 3064 * @param virtualDescendantId The id of the virtual descendant. 3065 */ 3066 public void setTraversalAfter(View root, int virtualDescendantId) { 3067 if (Build.VERSION.SDK_INT >= 22) { 3068 mInfo.setTraversalAfter(root, virtualDescendantId); 3069 } 3070 } 3071 3072 /** 3073 * Gets the window to which this node belongs. 3074 * 3075 * @return The window. 3076 * 3077 * @see android.accessibilityservice.AccessibilityService#getWindows() 3078 */ 3079 public AccessibilityWindowInfoCompat getWindow() { 3080 if (Build.VERSION.SDK_INT >= 21) { 3081 return AccessibilityWindowInfoCompat.wrapNonNullInstance(mInfo.getWindow()); 3082 } else { 3083 return null; 3084 } 3085 } 3086 3087 /** 3088 * Gets if the node can be dismissed. 3089 * 3090 * @return If the node can be dismissed. 3091 */ 3092 public boolean isDismissable() { 3093 if (Build.VERSION.SDK_INT >= 19) { 3094 return mInfo.isDismissable(); 3095 } else { 3096 return false; 3097 } 3098 } 3099 3100 /** 3101 * Sets if the node can be dismissed. 3102 * <p> 3103 * <strong>Note:</strong> Cannot be called from an 3104 * {@link android.accessibilityservice.AccessibilityService}. 3105 * This class is made immutable before being delivered to an AccessibilityService. 3106 * </p> 3107 * 3108 * @param dismissable If the node can be dismissed. 3109 */ 3110 public void setDismissable(boolean dismissable) { 3111 if (Build.VERSION.SDK_INT >= 19) { 3112 mInfo.setDismissable(dismissable); 3113 } 3114 } 3115 3116 /** 3117 * Gets if the node is editable. 3118 * 3119 * @return True if the node is editable, false otherwise. 3120 */ 3121 public boolean isEditable() { 3122 if (Build.VERSION.SDK_INT >= 18) { 3123 return mInfo.isEditable(); 3124 } else { 3125 return false; 3126 } 3127 } 3128 3129 /** 3130 * Sets whether this node is editable. 3131 * <p> 3132 * <strong>Note:</strong> Cannot be called from an 3133 * {@link android.accessibilityservice.AccessibilityService}. 3134 * This class is made immutable before being delivered to an AccessibilityService. 3135 * </p> 3136 * 3137 * @param editable True if the node is editable. 3138 * 3139 * @throws IllegalStateException If called from an AccessibilityService. 3140 */ 3141 public void setEditable(boolean editable) { 3142 if (Build.VERSION.SDK_INT >= 18) { 3143 mInfo.setEditable(editable); 3144 } 3145 } 3146 3147 /** 3148 * Gets if the node is a multi line editable text. 3149 * 3150 * @return True if the node is multi line. 3151 */ 3152 public boolean isMultiLine() { 3153 if (Build.VERSION.SDK_INT >= 19) { 3154 return mInfo.isMultiLine(); 3155 } else { 3156 return false; 3157 } 3158 } 3159 3160 /** 3161 * Sets if the node is a multi line editable text. 3162 * <p> 3163 * <strong>Note:</strong> Cannot be called from an 3164 * {@link android.accessibilityservice.AccessibilityService}. 3165 * This class is made immutable before being delivered to an AccessibilityService. 3166 * </p> 3167 * 3168 * @param multiLine True if the node is multi line. 3169 */ 3170 public void setMultiLine(boolean multiLine) { 3171 if (Build.VERSION.SDK_INT >= 19) { 3172 mInfo.setMultiLine(multiLine); 3173 } 3174 } 3175 3176 /** 3177 * Gets the tooltip text of this node. 3178 * 3179 * @return The tooltip text. 3180 */ 3181 @Nullable 3182 public CharSequence getTooltipText() { 3183 if (BuildCompat.isAtLeastP()) { 3184 return mInfo.getTooltipText(); 3185 } else if (Build.VERSION.SDK_INT >= 19) { 3186 return mInfo.getExtras().getCharSequence(TOOLTIP_TEXT_KEY); 3187 } 3188 return null; 3189 } 3190 3191 /** 3192 * Sets the tooltip text of this node. 3193 * <p>This method has no effect below API 19</p> 3194 * <p> 3195 * <strong>Note:</strong> Cannot be called from an 3196 * {@link android.accessibilityservice.AccessibilityService}. 3197 * This class is made immutable before being delivered to an AccessibilityService. 3198 * </p> 3199 * 3200 * @param tooltipText The tooltip text. 3201 * 3202 * @throws IllegalStateException If called from an AccessibilityService. 3203 */ 3204 public void setTooltipText(@Nullable CharSequence tooltipText) { 3205 if (BuildCompat.isAtLeastP()) { 3206 mInfo.setTooltipText(tooltipText); 3207 } else if (Build.VERSION.SDK_INT >= 19) { 3208 mInfo.getExtras().putCharSequence(TOOLTIP_TEXT_KEY, tooltipText); 3209 } 3210 } 3211 3212 /** 3213 * If this node represents a visually distinct region of the screen that may update separately 3214 * from the rest of the window, it is considered a pane. Set the pane title to indicate that 3215 * the node is a pane, and to provide a title for it. 3216 * <p>This method has no effect below API 19</p> 3217 * <p> 3218 * <strong>Note:</strong> Cannot be called from an 3219 * {@link android.accessibilityservice.AccessibilityService}. 3220 * This class is made immutable before being delivered to an AccessibilityService. 3221 * </p> 3222 * @param paneTitle The title of the window represented by this node. 3223 */ 3224 public void setPaneTitle(@Nullable CharSequence paneTitle) { 3225 if (BuildCompat.isAtLeastP()) { 3226 mInfo.setPaneTitle(paneTitle); 3227 } else if (Build.VERSION.SDK_INT >= 19) { 3228 mInfo.getExtras().putCharSequence(PANE_TITLE_KEY, paneTitle); 3229 } 3230 } 3231 3232 /** 3233 * Get the title of the pane represented by this node. 3234 * 3235 * @return The title of the pane represented by this node, or {@code null} if this node does 3236 * not represent a pane. 3237 */ 3238 public @Nullable CharSequence getPaneTitle() { 3239 if (BuildCompat.isAtLeastP()) { 3240 return mInfo.getPaneTitle(); 3241 } else if (Build.VERSION.SDK_INT >= 19) { 3242 return mInfo.getExtras().getCharSequence(PANE_TITLE_KEY); 3243 } 3244 return null; 3245 } 3246 3247 /** 3248 * Returns whether the node is explicitly marked as a focusable unit by a screen reader. Note 3249 * that {@code false} indicates that it is not explicitly marked, not that the node is not 3250 * a focusable unit. Screen readers should generally use other signals, such as 3251 * {@link #isFocusable()}, or the presence of text in a node, to determine what should receive 3252 * focus. 3253 * 3254 * @return {@code true} if the node is specifically marked as a focusable unit for screen 3255 * readers, {@code false} otherwise. 3256 */ 3257 public boolean isScreenReaderFocusable() { 3258 if (BuildCompat.isAtLeastP()) { 3259 return mInfo.isScreenReaderFocusable(); 3260 } 3261 return getBooleanProperty(BOOLEAN_PROPERTY_SCREEN_READER_FOCUSABLE); 3262 } 3263 3264 /** 3265 * Sets whether the node should be considered a focusable unit by a screen reader. 3266 * <p>This method has no effect below API 19</p> 3267 * <p> 3268 * <strong>Note:</strong> Cannot be called from an 3269 * {@link android.accessibilityservice.AccessibilityService}. 3270 * This class is made immutable before being delivered to an AccessibilityService. 3271 * </p> 3272 * 3273 * @param screenReaderFocusable {@code true} if the node is a focusable unit for screen readers, 3274 * {@code false} otherwise. 3275 */ 3276 public void setScreenReaderFocusable(boolean screenReaderFocusable) { 3277 if (BuildCompat.isAtLeastP()) { 3278 mInfo.setScreenReaderFocusable(screenReaderFocusable); 3279 } else { 3280 setBooleanProperty(BOOLEAN_PROPERTY_SCREEN_READER_FOCUSABLE, screenReaderFocusable); 3281 } 3282 } 3283 3284 /** 3285 * Returns whether the node's text represents a hint for the user to enter text. It should only 3286 * be {@code true} if the node has editable text. 3287 * 3288 * @return {@code true} if the text in the node represents a hint to the user, {@code false} 3289 * otherwise. 3290 */ 3291 public boolean isShowingHintText() { 3292 if (Build.VERSION.SDK_INT >= 26) { 3293 return mInfo.isShowingHintText(); 3294 } 3295 return getBooleanProperty(BOOLEAN_PROPERTY_IS_SHOWING_HINT); 3296 } 3297 3298 /** 3299 * Sets whether the node's text represents a hint for the user to enter text. It should only 3300 * be {@code true} if the node has editable text. 3301 * <p>This method has no effect below API 19</p> 3302 * <p> 3303 * <strong>Note:</strong> Cannot be called from an 3304 * {@link android.accessibilityservice.AccessibilityService}. 3305 * This class is made immutable before being delivered to an AccessibilityService. 3306 * </p> 3307 * 3308 * @param showingHintText {@code true} if the text in the node represents a hint to the user, 3309 * {@code false} otherwise. 3310 */ 3311 public void setShowingHintText(boolean showingHintText) { 3312 if (Build.VERSION.SDK_INT >= 26) { 3313 mInfo.setShowingHintText(showingHintText); 3314 } else { 3315 setBooleanProperty(BOOLEAN_PROPERTY_IS_SHOWING_HINT, showingHintText); 3316 } 3317 } 3318 3319 /** 3320 * Returns whether node represents a heading. 3321 * <p><strong>Note:</strong> Returns {@code true} if either {@link #setHeading(boolean)} 3322 * marks this node as a heading or if the node has a {@link CollectionItemInfoCompat} that marks 3323 * it as such, to accomodate apps that use the now-deprecated API.</p> 3324 * 3325 * @return {@code true} if the node is a heading, {@code false} otherwise. 3326 */ 3327 public boolean isHeading() { 3328 if (getBooleanProperty(BOOLEAN_PROPERTY_IS_HEADING)) return true; 3329 CollectionItemInfoCompat collectionItemInfo = getCollectionItemInfo(); 3330 return (collectionItemInfo != null) && (collectionItemInfo.isHeading()); 3331 } 3332 3333 /** 3334 * Sets whether the node represents a heading. 3335 * <p>This method has no effect below API 19</p> 3336 * <p> 3337 * <strong>Note:</strong> Cannot be called from an 3338 * {@link android.accessibilityservice.AccessibilityService}. 3339 * This class is made immutable before being delivered to an AccessibilityService. 3340 * </p> 3341 * 3342 * @param isHeading {@code true} if the node is a heading, {@code false} otherwise. 3343 */ 3344 public void setHeading(boolean isHeading) { 3345 setBooleanProperty(BOOLEAN_PROPERTY_IS_HEADING, isHeading); 3346 } 3347 3348 /** 3349 * Refreshes this info with the latest state of the view it represents. 3350 * <p> 3351 * <strong>Note:</strong> If this method returns false this info is obsolete 3352 * since it represents a view that is no longer in the view tree and should 3353 * be recycled. 3354 * </p> 3355 * @return Whether the refresh succeeded. 3356 */ 3357 public boolean refresh() { 3358 if (Build.VERSION.SDK_INT >= 18) { 3359 return mInfo.refresh(); 3360 } else { 3361 return false; 3362 } 3363 } 3364 3365 /** 3366 * Gets the custom role description. 3367 * @return The role description. 3368 */ 3369 public @Nullable CharSequence getRoleDescription() { 3370 if (Build.VERSION.SDK_INT >= 19) { 3371 return mInfo.getExtras().getCharSequence(ROLE_DESCRIPTION_KEY); 3372 } else { 3373 return null; 3374 } 3375 } 3376 3377 /** 3378 * Sets the custom role description. 3379 * 3380 * <p> 3381 * The role description allows you to customize the name for the view's semantic 3382 * role. For example, if you create a custom subclass of {@link android.view.View} 3383 * to display a menu bar, you could assign it the role description of "menu bar". 3384 * </p> 3385 * <p> 3386 * <strong>Warning:</strong> For consistency with other applications, you should 3387 * not use the role description to force accessibility services to describe 3388 * standard views (such as buttons or checkboxes) using specific wording. For 3389 * example, you should not set a role description of "check box" or "tick box" for 3390 * a standard {@link android.widget.CheckBox}. Instead let accessibility services 3391 * decide what feedback to provide. 3392 * </p> 3393 * <p> 3394 * <strong>Note:</strong> Cannot be called from an 3395 * {@link android.accessibilityservice.AccessibilityService}. 3396 * This class is made immutable before being delivered to an AccessibilityService. 3397 * </p> 3398 * 3399 * @param roleDescription The role description. 3400 */ 3401 public void setRoleDescription(@Nullable CharSequence roleDescription) { 3402 if (Build.VERSION.SDK_INT >= 19) { 3403 mInfo.getExtras().putCharSequence(ROLE_DESCRIPTION_KEY, roleDescription); 3404 } 3405 } 3406 3407 @Override 3408 public int hashCode() { 3409 return (mInfo == null) ? 0 : mInfo.hashCode(); 3410 } 3411 3412 @Override 3413 public boolean equals(Object obj) { 3414 if (this == obj) { 3415 return true; 3416 } 3417 if (obj == null) { 3418 return false; 3419 } 3420 if (getClass() != obj.getClass()) { 3421 return false; 3422 } 3423 AccessibilityNodeInfoCompat other = (AccessibilityNodeInfoCompat) obj; 3424 if (mInfo == null) { 3425 if (other.mInfo != null) { 3426 return false; 3427 } 3428 } else if (!mInfo.equals(other.mInfo)) { 3429 return false; 3430 } 3431 return true; 3432 } 3433 3434 @Override 3435 public String toString() { 3436 StringBuilder builder = new StringBuilder(); 3437 builder.append(super.toString()); 3438 3439 Rect bounds = new Rect(); 3440 3441 getBoundsInParent(bounds); 3442 builder.append("; boundsInParent: " + bounds); 3443 3444 getBoundsInScreen(bounds); 3445 builder.append("; boundsInScreen: " + bounds); 3446 3447 builder.append("; packageName: ").append(getPackageName()); 3448 builder.append("; className: ").append(getClassName()); 3449 builder.append("; text: ").append(getText()); 3450 builder.append("; contentDescription: ").append(getContentDescription()); 3451 builder.append("; viewId: ").append(getViewIdResourceName()); 3452 3453 builder.append("; checkable: ").append(isCheckable()); 3454 builder.append("; checked: ").append(isChecked()); 3455 builder.append("; focusable: ").append(isFocusable()); 3456 builder.append("; focused: ").append(isFocused()); 3457 builder.append("; selected: ").append(isSelected()); 3458 builder.append("; clickable: ").append(isClickable()); 3459 builder.append("; longClickable: ").append(isLongClickable()); 3460 builder.append("; enabled: ").append(isEnabled()); 3461 builder.append("; password: ").append(isPassword()); 3462 builder.append("; scrollable: " + isScrollable()); 3463 3464 builder.append("; ["); 3465 for (int actionBits = getActions(); actionBits != 0;) { 3466 final int action = 1 << Integer.numberOfTrailingZeros(actionBits); 3467 actionBits &= ~action; 3468 builder.append(getActionSymbolicName(action)); 3469 if (actionBits != 0) { 3470 builder.append(", "); 3471 } 3472 } 3473 builder.append("]"); 3474 3475 return builder.toString(); 3476 } 3477 3478 private void setBooleanProperty(int property, boolean value) { 3479 Bundle extras = getExtras(); 3480 if (extras != null) { 3481 int booleanProperties = extras.getInt(BOOLEAN_PROPERTY_KEY, 0); 3482 booleanProperties &= ~property; 3483 booleanProperties |= (value) ? property : 0; 3484 extras.putInt(BOOLEAN_PROPERTY_KEY, booleanProperties); 3485 } 3486 } 3487 3488 private boolean getBooleanProperty(int property) { 3489 Bundle extras = getExtras(); 3490 if (extras == null) return false; 3491 return (extras.getInt(BOOLEAN_PROPERTY_KEY, 0) & property) == property; 3492 } 3493 3494 private static String getActionSymbolicName(int action) { 3495 switch (action) { 3496 case ACTION_FOCUS: 3497 return "ACTION_FOCUS"; 3498 case ACTION_CLEAR_FOCUS: 3499 return "ACTION_CLEAR_FOCUS"; 3500 case ACTION_SELECT: 3501 return "ACTION_SELECT"; 3502 case ACTION_CLEAR_SELECTION: 3503 return "ACTION_CLEAR_SELECTION"; 3504 case ACTION_CLICK: 3505 return "ACTION_CLICK"; 3506 case ACTION_LONG_CLICK: 3507 return "ACTION_LONG_CLICK"; 3508 case ACTION_ACCESSIBILITY_FOCUS: 3509 return "ACTION_ACCESSIBILITY_FOCUS"; 3510 case ACTION_CLEAR_ACCESSIBILITY_FOCUS: 3511 return "ACTION_CLEAR_ACCESSIBILITY_FOCUS"; 3512 case ACTION_NEXT_AT_MOVEMENT_GRANULARITY: 3513 return "ACTION_NEXT_AT_MOVEMENT_GRANULARITY"; 3514 case ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: 3515 return "ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY"; 3516 case ACTION_NEXT_HTML_ELEMENT: 3517 return "ACTION_NEXT_HTML_ELEMENT"; 3518 case ACTION_PREVIOUS_HTML_ELEMENT: 3519 return "ACTION_PREVIOUS_HTML_ELEMENT"; 3520 case ACTION_SCROLL_FORWARD: 3521 return "ACTION_SCROLL_FORWARD"; 3522 case ACTION_SCROLL_BACKWARD: 3523 return "ACTION_SCROLL_BACKWARD"; 3524 case ACTION_CUT: 3525 return "ACTION_CUT"; 3526 case ACTION_COPY: 3527 return "ACTION_COPY"; 3528 case ACTION_PASTE: 3529 return "ACTION_PASTE"; 3530 case ACTION_SET_SELECTION: 3531 return "ACTION_SET_SELECTION"; 3532 default: 3533 return"ACTION_UNKNOWN"; 3534 } 3535 } 3536 } 3537