Java Code Examples for androidx.core.view.accessibility.AccessibilityNodeInfoCompat#ACTION_SCROLL_BACKWARD
The following examples show how to use
androidx.core.view.accessibility.AccessibilityNodeInfoCompat#ACTION_SCROLL_BACKWARD .
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 |
@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 |
@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 |
@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 |
/** * 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: NodeActionMenuItem.java From talkback with Apache License 2.0 | 5 votes |
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 6
Source File: FocusProcessorForLogicalNavigation.java From talkback with Apache License 2.0 | 5 votes |
/** * 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 7
Source File: ProcessorVolumeStream.java From talkback with Apache License 2.0 | 5 votes |
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 8
Source File: SearchScreenOverlay.java From talkback with Apache License 2.0 | 5 votes |
/** * 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 9
Source File: BaseSlider.java From material-components-android with Apache License 2.0 | 4 votes |
@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 10
Source File: AccessibilityNodeInfoUtils.java From talkback with Apache License 2.0 | 4 votes |
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 11
Source File: NodeActionMenuItem.java From talkback with Apache License 2.0 | 4 votes |
/** 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 12
Source File: OptionScanHighlighter.java From talkback with Apache License 2.0 | 4 votes |
@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 13
Source File: FocusProcessorForLogicalNavigation.java From talkback with Apache License 2.0 | 4 votes |
/** * 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 14
Source File: SearchScreenOverlay.java From talkback with Apache License 2.0 | 4 votes |
/** * 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 15
Source File: RadialPickerLayout.java From MaterialDateTimePicker with Apache License 2.0 | 4 votes |
/** * 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; }