Java Code Examples for androidx.core.view.accessibility.AccessibilityNodeInfoCompat#ACTION_SCROLL_FORWARD

The following examples show how to use androidx.core.view.accessibility.AccessibilityNodeInfoCompat#ACTION_SCROLL_FORWARD . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: SliderPager.java    From Android-Image-Slider with Apache License 2.0 6 votes vote down vote up
@Override
public boolean performAccessibilityAction(View host, int action, Bundle args) {
    if (super.performAccessibilityAction(host, action, args)) {
        return true;
    }
    switch (action) {
        case AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD: {
            if (canScrollHorizontally(1)) {
                setCurrentItem(mCurItem + 1);
                return true;
            }
        }
        return false;
        case AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD: {
            if (canScrollHorizontally(-1)) {
                setCurrentItem(mCurItem - 1);
                return true;
            }
        }
        return false;
    }
    return false;
}
 
Example 2
Source File: VerticalViewPager.java    From DKVideoPlayer with Apache License 2.0 6 votes vote down vote up
@Override
public boolean performAccessibilityAction(View host, int action, Bundle args) {
    if (super.performAccessibilityAction(host, action, args)) {
        return true;
    }
    switch (action) {
        case AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD: {
            if (internalCanScrollVertically(1)) {
                setCurrentItem(mCurItem + 1);
                return true;
            }
        }
        return false;
        case AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD: {
            if (internalCanScrollVertically(-1)) {
                setCurrentItem(mCurItem - 1);
                return true;
            }
        }
        return false;
    }
    return false;
}
 
Example 3
Source File: CustomViewPager.java    From AsteroidOSSync with GNU General Public License v3.0 6 votes vote down vote up
@Override
public boolean performAccessibilityAction(View host, int action, Bundle args) {
    if (super.performAccessibilityAction(host, action, args)) {
        return true;
    }
    switch (action) {
        case AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD: {
            if (canScrollHorizontally(1)) {
                setCurrentItem(mCurItem + 1);
                return true;
            }
        } return false;
        case AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD: {
            if (canScrollHorizontally(-1)) {
                setCurrentItem(mCurItem - 1);
                return true;
            }
        } return false;
    }
    return false;
}
 
Example 4
Source File: TraversalStrategyUtils.java    From talkback with Apache License 2.0 6 votes vote down vote up
/**
 * Returns the scroll action for the given {@link TraversalStrategy.SearchDirection} if the scroll
 * action is available on the current SDK version. Otherwise, returns 0.
 */
public static int convertSearchDirectionToScrollAction(
    @TraversalStrategy.SearchDirection int direction) {
  if (direction == TraversalStrategy.SEARCH_FOCUS_FORWARD) {
    return AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD;
  } else if (direction == TraversalStrategy.SEARCH_FOCUS_BACKWARD) {
    return AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD;
  } else {
    if (direction == TraversalStrategy.SEARCH_FOCUS_LEFT) {
      return AccessibilityAction.ACTION_SCROLL_LEFT.getId();
    } else if (direction == TraversalStrategy.SEARCH_FOCUS_RIGHT) {
      return AccessibilityAction.ACTION_SCROLL_RIGHT.getId();
    } else if (direction == TraversalStrategy.SEARCH_FOCUS_UP) {
      return AccessibilityAction.ACTION_SCROLL_UP.getId();
    } else if (direction == TraversalStrategy.SEARCH_FOCUS_DOWN) {
      return AccessibilityAction.ACTION_SCROLL_DOWN.getId();
    }
  }

  return 0;
}
 
Example 5
Source File: OptionManager.java    From talkback with Apache License 2.0 6 votes vote down vote up
/**
 * Support legacy scroll key actions. Perform a scroll on the currently selected item, if it is
 * scrollable, or a scrollable parent if one can be found. If the scroll action is accepted, focus
 * is cleared.
 *
 * @param scrollAction Either {@code AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD} or {@code
 *     AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD}.
 */
public void performScrollAction(int scrollAction) {
  SwitchAccessNodeCompat compat = findCurrentlyActiveNode();
  while (compat != null) {
    if (compat.isScrollable()) {
      if (compat.performAction(scrollAction)) {
        clearFocus();
        if (scanListener != null) {
          ScanStateChangeTrigger trigger =
              (scrollAction == AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD)
                  ? ScanStateChangeTrigger.KEY_SCROLL_FORWARD
                  : ScanStateChangeTrigger.KEY_SCROLL_BACKWARD;
          scanListener.onScanSelection(trigger);
        }
      }
      compat.recycle();
      return;
    }
    SwitchAccessNodeCompat parent = compat.getParent();
    compat.recycle();
    compat = parent;
  }
}
 
Example 6
Source File: NodeActionMenuItem.java    From talkback with Apache License 2.0 5 votes vote down vote up
private static SwitchAccessMenuItemEnum.MenuItem getMenuItemForAction(SwitchAccessAction action) {
  switch (action.getId()) {
    case AccessibilityNodeInfoCompat.ACTION_CLICK:
      return SwitchAccessMenuItemEnum.MenuItem.ACTION_MENU_CLICK;
    case AccessibilityNodeInfoCompat.ACTION_LONG_CLICK:
      return SwitchAccessMenuItemEnum.MenuItem.ACTION_MENU_LONG_CLICK;
    case AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD:
      return SwitchAccessMenuItemEnum.MenuItem.ACTION_MENU_SCROLL_FORWARD;
    case AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD:
      return SwitchAccessMenuItemEnum.MenuItem.ACTION_MENU_SCROLL_BACKWARD;
    case AccessibilityNodeInfoCompat.ACTION_DISMISS:
      return SwitchAccessMenuItemEnum.MenuItem.ACTION_MENU_DISMISS;
    case AccessibilityNodeInfoCompat.ACTION_COLLAPSE:
      return SwitchAccessMenuItemEnum.MenuItem.ACTION_MENU_COLLAPSE;
    case AccessibilityNodeInfoCompat.ACTION_EXPAND:
      return SwitchAccessMenuItemEnum.MenuItem.ACTION_MENU_EXPAND;
    case AccessibilityNodeInfoCompat.ACTION_SET_SELECTION:
      return getMenuItemForSetSelectionAction(action);
    case AccessibilityNodeInfoCompat.ACTION_CUT:
      return getMenuItemForCutAction(action);
    case AccessibilityNodeInfoCompat.ACTION_COPY:
      return getMenuItemForCopyAction(action);
    case AccessibilityNodeInfoCompat.ACTION_PASTE:
      return SwitchAccessMenuItemEnum.MenuItem.ACTION_MENU_PASTE;
    case TextEditingUtils.ACTION_DELETE_TEXT:
      return getMenuItemForDeleteTextAction(action);
    case AccessibilityNodeInfoCompat.ACTION_NEXT_AT_MOVEMENT_GRANULARITY:
      return getMenuItemForNextAtMovementGranularityAction(action);
    case AccessibilityNodeInfoCompat.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY:
      return getMenuItemForPreviousAtMovementGranularityAction(action);
    case TextEditingUtils.ACTION_UNDO:
      return SwitchAccessMenuItemEnum.MenuItem.ACTION_MENU_UNDO;
    case TextEditingUtils.ACTION_REDO:
      return SwitchAccessMenuItemEnum.MenuItem.ACTION_MENU_REDO;
    default:
      // Other actions such as "App info", "Add to home screen" etc.
      return SwitchAccessMenuItemEnum.MenuItem.ACTION_MENU_CUSTOM_ACTION;
  }
}
 
Example 7
Source File: FocusProcessorForLogicalNavigation.java    From talkback with Apache License 2.0 5 votes vote down vote up
/**
 * Returns scrollable node filter for given {@link NavigationAction}.
 *
 * <p>This is consistent with what we used in {@link
 * TraversalStrategyUtils#isAutoScrollEdgeListItem(AccessibilityNodeInfoCompat, boolean, int,
 * TraversalStrategy)}. It consists of {@link NodeActionFilter} to check supported scroll action,
 * and {@link AccessibilityNodeInfoUtils#FILTER_AUTO_SCROLL} to match white-listed {@link Role}.
 */
@Nullable
private static Filter<AccessibilityNodeInfoCompat> getScrollFilter(
    NavigationAction navigationAction) {
  final int scrollAction;
  switch (navigationAction.actionType) {
    case NavigationAction.SCROLL_FORWARD:
      scrollAction = AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD;
      break;
    case NavigationAction.SCROLL_BACKWARD:
      scrollAction = AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD;
      break;
    case NavigationAction.DIRECTIONAL_NAVIGATION:
      scrollAction =
          TraversalStrategyUtils.convertSearchDirectionToScrollAction(
              navigationAction.searchDirection);
      break;
    default:
      scrollAction = 0;
      break;
  }

  if (scrollAction == 0) {
    return null;
  }

  if ((navigationAction.actionType == NavigationAction.SCROLL_FORWARD)
      || (navigationAction.actionType == NavigationAction.SCROLL_BACKWARD)) {
    return new NodeActionFilter(scrollAction).and(SCROLLABLE_ROLE_FILTER_FOR_SCROLL_GESTURE);
  } else {
    return new NodeActionFilter(scrollAction)
        .and(SCROLLABLE_ROLE_FILTER_FOR_DIRECTION_NAVIGATION);
  }
}
 
Example 8
Source File: ProcessorVolumeStream.java    From talkback with Apache License 2.0 5 votes vote down vote up
private void navigateSlider(
    int button, @NonNull AccessibilityNodeInfoCompat node, EventId eventId) {
  int action;
  if (button == VolumeButtonPatternDetector.VOLUME_UP) {
    action = AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD;
  } else if (button == VolumeButtonPatternDetector.VOLUME_DOWN) {
    action = AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD;
  } else {
    return;
  }

  PerformActionUtils.performAction(node, action, eventId);
}
 
Example 9
Source File: SearchScreenOverlay.java    From talkback with Apache License 2.0 5 votes vote down vote up
/**
 * Gets the filter to find the scrollable node according to the specified {@code action} except
 * SeekBar because there is no text that can be searched.
 *
 * @param action filter action to find the nodes, could be {@code
 *     AccessibilityNodeInfoUtils.FILTER_COULD_SCROLL_FORWARD} or {@code
 *     AccessibilityNodeInfoUtils.FILTER_COULD_SCROLL_BACKWARD}
 * @return the node filter or null if the specified action is not valid
 */
static Filter<AccessibilityNodeInfoCompat> getScrollFilter(int action) {
  if (action == AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD) {
    return AccessibilityNodeInfoUtils.FILTER_COULD_SCROLL_FORWARD.and(FILTER_NO_SEEK_BAR);
  } else if (action == AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD) {
    return AccessibilityNodeInfoUtils.FILTER_COULD_SCROLL_BACKWARD.and(FILTER_NO_SEEK_BAR);
  } else {
    return null;
  }
}
 
Example 10
Source File: BaseSlider.java    From material-components-android with Apache License 2.0 4 votes vote down vote up
@Override
protected boolean onPerformActionForVirtualView(
    int virtualViewId, int action, Bundle arguments) {
  if (!slider.isEnabled()) {
    return false;
  }

  switch (action) {
    case android.R.id.accessibilityActionSetProgress:
      {
        if (arguments == null
            || !arguments.containsKey(
                AccessibilityNodeInfoCompat.ACTION_ARGUMENT_PROGRESS_VALUE)) {
          return false;
        }
        float value =
            arguments.getFloat(AccessibilityNodeInfoCompat.ACTION_ARGUMENT_PROGRESS_VALUE);
        if (slider.snapThumbToValue(virtualViewId, value)) {
          slider.updateHaloHotspot();
          slider.postInvalidate();
          invalidateVirtualView(virtualViewId);
          return true;
        }
        return false;
      }
    case AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD:
    case AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD:
      {
        float increment = slider.calculateStepIncrement(20);
        if (action == AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD) {
          increment = -increment;
        }

        // Swap the increment if we're in RTL.
        if (slider.isRtl()) {
          increment = -increment;
        }

        List<Float> values = slider.getValues();
        float clamped =
            clamp(
                values.get(virtualViewId) + increment,
                slider.getValueFrom(),
                slider.getValueTo());
        if (slider.snapThumbToValue(virtualViewId, clamped)) {
          slider.updateHaloHotspot();
          slider.postInvalidate();
          invalidateVirtualView(virtualViewId);
          return true;
        }
        return false;
      }
    default:
      return false;
  }
}
 
Example 11
Source File: AccessibilityNodeInfoUtils.java    From talkback with Apache License 2.0 4 votes vote down vote up
public static String actionToString(int action) {
  switch (action) {
    case AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS:
      return "ACTION_ACCESSIBILITY_FOCUS";
    case AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS:
      return "ACTION_CLEAR_ACCESSIBILITY_FOCUS";
    case AccessibilityNodeInfoCompat.ACTION_CLEAR_FOCUS:
      return "ACTION_CLEAR_FOCUS";
    case AccessibilityNodeInfoCompat.ACTION_CLEAR_SELECTION:
      return "ACTION_CLEAR_SELECTION";
    case AccessibilityNodeInfoCompat.ACTION_CLICK:
      return "ACTION_CLICK";
    case AccessibilityNodeInfoCompat.ACTION_COLLAPSE:
      return "ACTION_COLLAPSE";
    case AccessibilityNodeInfoCompat.ACTION_COPY:
      return "ACTION_COPY";
    case AccessibilityNodeInfoCompat.ACTION_CUT:
      return "ACTION_CUT";
    case AccessibilityNodeInfoCompat.ACTION_DISMISS:
      return "ACTION_DISMISS";
    case AccessibilityNodeInfoCompat.ACTION_EXPAND:
      return "ACTION_EXPAND";
    case AccessibilityNodeInfoCompat.ACTION_FOCUS:
      return "ACTION_FOCUS";
    case AccessibilityNodeInfoCompat.ACTION_LONG_CLICK:
      return "ACTION_LONG_CLICK";
    case AccessibilityNodeInfoCompat.ACTION_NEXT_AT_MOVEMENT_GRANULARITY:
      return "ACTION_NEXT_AT_MOVEMENT_GRANULARITY";
    case AccessibilityNodeInfoCompat.ACTION_NEXT_HTML_ELEMENT:
      return "ACTION_NEXT_HTML_ELEMENT";
    case AccessibilityNodeInfoCompat.ACTION_PASTE:
      return "ACTION_PASTE";
    case AccessibilityNodeInfoCompat.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY:
      return "ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY";
    case AccessibilityNodeInfoCompat.ACTION_PREVIOUS_HTML_ELEMENT:
      return "ACTION_PREVIOUS_HTML_ELEMENT";
    case AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD:
      return "ACTION_SCROLL_BACKWARD";
    case AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD:
      return "ACTION_SCROLL_FORWARD";
    case AccessibilityNodeInfoCompat.ACTION_SELECT:
      return "ACTION_SELECT";
    case AccessibilityNodeInfoCompat.ACTION_SET_SELECTION:
      return "ACTION_SET_SELECTION";
    case AccessibilityNodeInfoCompat.ACTION_SET_TEXT:
      return "ACTION_SET_TEXT";
    default:
      return "(unhandled)";
  }
}
 
Example 12
Source File: NodeActionMenuItem.java    From talkback with Apache License 2.0 4 votes vote down vote up
/** Returns an icon resource id associated with the current action. */
@Override
public int getIconResource() {
  int actionId = action.getId();
  switch (actionId) {
    case AccessibilityNodeInfoCompat.ACTION_CLICK:
      return R.drawable.ic_select;
    case AccessibilityNodeInfoCompat.ACTION_LONG_CLICK:
      return R.drawable.ic_long_press;
    case AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD:
      return R.drawable.ic_scroll_down;
    case AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD:
      return R.drawable.ic_scroll_up;
    case AccessibilityNodeInfoCompat.ACTION_DISMISS:
      return R.drawable.ic_dismiss;
    case AccessibilityNodeInfoCompat.ACTION_NEXT_AT_MOVEMENT_GRANULARITY:
    case AccessibilityNodeInfoCompat.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY:
      return R.drawable.ic_text;
    case AccessibilityNodeInfoCompat.ACTION_COLLAPSE:
      return R.drawable.ic_collapse;
    case AccessibilityNodeInfoCompat.ACTION_EXPAND:
      return R.drawable.ic_expand;
    case AccessibilityNodeInfoCompat.ACTION_SET_SELECTION:
      return R.drawable.ic_highlight_text;
    case AccessibilityNodeInfoCompat.ACTION_CUT:
      return R.drawable.ic_cut;
    case AccessibilityNodeInfoCompat.ACTION_COPY:
      return R.drawable.ic_copy;
    case AccessibilityNodeInfoCompat.ACTION_PASTE:
      return R.drawable.ic_paste;
    case TextEditingUtils.ACTION_DELETE_TEXT:
      return R.drawable.ic_delete_text;
    case TextEditingUtils.ACTION_UNDO:
      return R.drawable.ic_undo;
    case TextEditingUtils.ACTION_REDO:
      return R.drawable.ic_redo;
    default:
      // We don't know what the action is. Don't show an icon.
      return 0;
  }
}
 
Example 13
Source File: OptionScanHighlighter.java    From talkback with Apache License 2.0 4 votes vote down vote up
@Override
public void run() {
  int[] layoutCoordinates = new int[2];
  for (TreeScanLeafNode node : nodes) {
    Rect rect = node.getRectForNodeHighlight();
    if (rect == null) {
      continue;
    }
    int halfStrokeWidth = (int) highlightPaint.getStrokeWidth() / 2;
    GradientDrawable mainHighlightDrawable = getHighlightDrawable(halfStrokeWidth, rect);
    @KeyFor("MAIN_TO_OUTER_HIGHLIGHT_COLOR_MAP")
    int mainPaintColor = highlightPaint.getColor();
    mainHighlightDrawable.setStroke(halfStrokeWidth, mainPaintColor);

    GradientDrawable outerHighlightDrawable = null;
    if (MAIN_TO_OUTER_HIGHLIGHT_COLOR_MAP.containsKey(mainPaintColor)) {
      outerHighlightDrawable = getHighlightDrawable(halfStrokeWidth, rect);
      outerHighlightDrawable.setStroke(
          halfStrokeWidth / 2, MAIN_TO_OUTER_HIGHLIGHT_COLOR_MAP.get(mainPaintColor));
    }

    // Determine which scroll arrows we should show.
    boolean shouldShowUpArrow = false;
    boolean shouldShowDownArrow = false;
    boolean shouldShowRightArrow = false;
    boolean shouldShowLeftArrow = false;
    boolean supportsScrollForward = false;
    boolean supportsScrollBackward = false;
    if (FeatureFlags.scrollArrows()
        && (VERSION.SDK_INT >= VERSION_CODES.N)
        && node.isScrollable()) {
      for (AccessibilityActionCompat action : node.getActionList()) {
        if (action.getId() == AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD) {
          supportsScrollBackward = true;
        } else if (action.getId() == AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD) {
          supportsScrollForward = true;
        } else if (VERSION.SDK_INT >= VERSION_CODES.N_MR1) {
          if (action.getId() == AccessibilityActionCompat.ACTION_SCROLL_UP.getId()) {
            shouldShowUpArrow = true;
          } else if (action.getId() == AccessibilityActionCompat.ACTION_SCROLL_DOWN.getId()) {
            shouldShowDownArrow = true;
          } else if (action.getId() == AccessibilityActionCompat.ACTION_SCROLL_RIGHT.getId()) {
            shouldShowRightArrow = true;
          } else if (action.getId() == AccessibilityActionCompat.ACTION_SCROLL_LEFT.getId()) {
            shouldShowLeftArrow = true;
          }
        }
      }

      // If only the less granular version of a scroll action is supported, show the possible
      // scroll directions for that scroll action.
      if (supportsScrollForward && !shouldShowDownArrow && !shouldShowRightArrow) {
        shouldShowDownArrow = true;
        shouldShowRightArrow = true;
      }
      if (supportsScrollBackward && !shouldShowUpArrow && !shouldShowLeftArrow) {
        shouldShowUpArrow = true;
        shouldShowLeftArrow = true;
      }
    }

    ImageView imageView = new ImageView(overlayController.getContext());
    imageView.setBackground(
        getFinalHighlightDrawable(
            shouldShowUpArrow,
            shouldShowDownArrow,
            shouldShowRightArrow,
            shouldShowLeftArrow,
            mainHighlightDrawable,
            outerHighlightDrawable));

    // Align image with node we're highlighting
    final RelativeLayout.LayoutParams layoutParams =
        new RelativeLayout.LayoutParams(rect.width(), rect.height());
    layoutParams.leftMargin = rect.left - layoutCoordinates[0];
    layoutParams.topMargin = rect.top - layoutCoordinates[1];
    imageView.setLayoutParams(layoutParams);
    overlayController.addViewAndShow(imageView);
  }
}
 
Example 14
Source File: FocusProcessorForLogicalNavigation.java    From talkback with Apache License 2.0 4 votes vote down vote up
/**
 * Handles {@link NavigationAction#SCROLL_FORWARD} and {@link NavigationAction#SCROLL_BACKWARD}
 * actions.
 *
 * @return {@code true} if any accessibility action is successfully performed.
 */
private boolean onScrollAction(
    AccessibilityNodeInfoCompat pivot, NavigationAction navigationAction, EventId eventId) {
  // Node to be recycled.
  AccessibilityNodeInfoCompat scrollableNode = null;
  AccessibilityNodeInfoCompat rootNode = null;
  try {
    final int scrollAction;
    if (navigationAction.actionType == NavigationAction.SCROLL_FORWARD) {
      scrollAction = AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD;
    } else if (navigationAction.actionType == NavigationAction.SCROLL_BACKWARD) {
      scrollAction = AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD;
    } else {
      throw new IllegalArgumentException("Unknown scroll action.");
    }

    final Filter<AccessibilityNodeInfoCompat> nodeFilter = getScrollFilter(navigationAction);
    if (nodeFilter == null) {
      return false;
    }

    if (AccessibilityNodeInfoUtils.supportsAction(pivot, scrollAction)) {
      // Try to scroll the node itself first. It's useful when focusing on a SeekBar.
      scrollableNode = AccessibilityNodeInfoUtils.obtain(pivot);
    } else if ((pivot != null) && pivot.isAccessibilityFocused()) {
      scrollableNode = AccessibilityNodeInfoUtils.getSelfOrMatchingAncestor(pivot, nodeFilter);
    }

    if (scrollableNode == null) {
      rootNode = AccessibilityNodeInfoUtils.getRoot(pivot);
      if (rootNode != null) {
        scrollableNode = AccessibilityNodeInfoUtils.searchFromBfs(rootNode, nodeFilter);
      }
    }
    return (scrollableNode != null)
        && performScrollActionInternal(
            ScrollEventInterpreter.ACTION_SCROLL_SHORTCUT,
            scrollableNode,
            pivot,
            scrollAction,
            navigationAction,
            eventId);
  } finally {
    AccessibilityNodeInfoUtils.recycleNodes(scrollableNode, rootNode);
  }
}
 
Example 15
Source File: SearchScreenOverlay.java    From talkback with Apache License 2.0 4 votes vote down vote up
/**
 * Performs scroll action on the scrollable node of {@link #initialFocusedWindow} except SeekBar
 * because there is no text that can be searched.
 *
 * @param action The accessibility scroll action. Should be {@link
 *     AccessibilityNodeInfoCompat#ACTION_SCROLL_BACKWARD} or {@link
 *     AccessibilityNodeInfoCompat#ACTION_SCROLL_FORWARD}.
 */
private boolean scrollScreen(int action) {
  if (action != AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD
      && action != AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD) {
    return false;
  }

  AccessibilityNode scrollableNode = getScrollableNode(action);
  if (scrollableNode == null) {
    refreshUiState();
    return false;
  }

  // Check if we need to update focused node after scrolling, the condition is copied from
  // FocusProcessorForLogicalNavigation.performScrollActionInternal()
  boolean needToUpdateFocus =
      (initialFocusedNode != null) && initialFocusedNode.hasAncestor(scrollableNode);

  scrollCallback =
      new AutoScrollCallback() {
        @Override
        public void onAutoScrolled(AccessibilityNode scrolledNode, EventId eventId) {
          if (needToUpdateFocus) {
            // Need to update focus node to get next correct scrollable node.
            // Refer to .
            onScrolledWithFocusUpdate(scrolledNode, action);
          } else {
            onScrolled();
          }
        }

        @Override
        public void onAutoScrollFailed(AccessibilityNode nodeToScroll) {
          searchStrategy.cacheNodeTree(initialFocusedWindow);
          // Search again since the result was already cleared before scrolling start.
          searchStrategy.searchKeyword(keywordEditText.getText().toString());

          // Disable the button since the scroll is failed, keep user from requesting again.
          if (action == AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD) {
            disableImageButton(prevScreenButton);
          } else {
            disableImageButton(nextScreenButton);
          }
        }
      };

  boolean result = false;

  try {
    pipeline.returnFeedback(
        EVENT_ID_UNTRACKED,
        Feedback.scroll(scrollableNode, ACTION_AUTO_SCROLL, action, Source.SEARCH));
  } finally {
    AccessibilityNode.recycle("SearchScreenOverlay.scrollScreen()", scrollableNode);
  }

  if (result) {
    // Screen is scrolled, clears previous search results.
    clearSearchResult();
  } else {
    // User clicks on the scroll button but the scrolling doesn't happen. Refresh button's state
    // to see if they should be disabled.
    refreshUiState();
  }

  return result;
}
 
Example 16
Source File: RadialPickerLayout.java    From MaterialDateTimePicker with Apache License 2.0 4 votes vote down vote up
/**
 * When scroll forward/backward events are received, jump the time to the higher/lower
 * discrete, visible value on the circle.
 */
@Override
public boolean performAccessibilityAction(int action, Bundle arguments) {
    if (super.performAccessibilityAction(action, arguments)) {
        return true;
    }

    int changeMultiplier = 0;
    int forward;
    int backward;
    if (Build.VERSION.SDK_INT >= 16) {
        forward = AccessibilityNodeInfo.ACTION_SCROLL_FORWARD;
        backward = AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD;
    } else {
        forward = AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD;
        backward = AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD;
    }
    if (action == forward) {
        changeMultiplier = 1;
    } else if (action == backward) {
        changeMultiplier = -1;
    }
    if (changeMultiplier != 0) {
        int value = getCurrentlyShowingValue();
        int stepSize = 0;
        int currentItemShowing = getCurrentItemShowing();
        if (currentItemShowing == HOUR_INDEX) {
            stepSize = HOUR_VALUE_TO_DEGREES_STEP_SIZE;
            value %= 12;
        } else if (currentItemShowing == MINUTE_INDEX) {
            stepSize = MINUTE_VALUE_TO_DEGREES_STEP_SIZE;
        } else if (currentItemShowing == SECOND_INDEX) {
            stepSize = SECOND_VALUE_TO_DEGREES_STEP_SIZE;
        }

        int degrees = value * stepSize;
        degrees = snapOnly30s(degrees, changeMultiplier);
        value = degrees / stepSize;
        int maxValue = 0;
        int minValue = 0;
        if (currentItemShowing == HOUR_INDEX) {
            if (mIs24HourMode) {
                maxValue = 23;
            } else {
                maxValue = 12;
                minValue = 1;
            }
        } else {
            maxValue = 55;
        }
        if (value > maxValue) {
            // If we scrolled forward past the highest number, wrap around to the lowest.
            value = minValue;
        } else if (value < minValue) {
            // If we scrolled backward past the lowest number, wrap around to the highest.
            value = maxValue;
        }

        Timepoint newSelection;
        switch(currentItemShowing) {
            case HOUR_INDEX:
                newSelection = new Timepoint(
                        value,
                        mCurrentTime.getMinute(),
                        mCurrentTime.getSecond()
                );
                break;
            case MINUTE_INDEX:
                newSelection = new Timepoint(
                        mCurrentTime.getHour(),
                        value,
                        mCurrentTime.getSecond()
                );
                break;
            case SECOND_INDEX:
                newSelection = new Timepoint(
                        mCurrentTime.getHour(),
                        mCurrentTime.getMinute(),
                        value
                );
                break;
            default:
                newSelection = mCurrentTime;
        }

        setItem(currentItemShowing, newSelection);
        mListener.onValueSelected(newSelection);
        return true;
    }

    return false;
}