From af78b59af19264105b8ce856defa5342d6fd584a Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Wed, 11 Nov 2015 09:25:38 -0800 Subject: Make sure pages are always accessible via left/right arrow keys. - Handle NextPageFirstItem as first focusable item in reading order - Handle PreviousPageLastItem as last focusable item in reading order - Check the hotseat after the workspace in both cases above - Dpad horizontal navigation (left/right) uses these as a last resort (Rule3) to guarantee an item takes focus if a page exists Note that it is necessary to search for a focusable item because widgets are not yet focusable. Bug: 25591057 Change-Id: I953648bd76c657d660a38427fdd4108bf9963c23 --- src/com/android/launcher3/FocusHelper.java | 97 +++++++++++++++++++++++++++--- 1 file changed, 87 insertions(+), 10 deletions(-) (limited to 'src/com/android/launcher3/FocusHelper.java') diff --git a/src/com/android/launcher3/FocusHelper.java b/src/com/android/launcher3/FocusHelper.java index 4709488a0..b243da3d5 100644 --- a/src/com/android/launcher3/FocusHelper.java +++ b/src/com/android/launcher3/FocusHelper.java @@ -374,7 +374,9 @@ public class FocusHelper { // Process the focus. int newIconIndex = FocusLogic.handleKeyEvent(keyCode, countX, countY, matrix, iconIndex, pageIndex, pageCount, Utilities.isRtl(v.getResources())); + boolean isRtl = Utilities.isRtl(v.getResources()); View newIcon = null; + CellLayout workspaceLayout = (CellLayout) workspace.getChildAt(pageIndex); switch (newIconIndex) { case FocusLogic.NOOP: if (keyCode == KeyEvent.KEYCODE_DPAD_UP) { @@ -396,20 +398,30 @@ public class FocusHelper { newIconIndex = FocusLogic.handleKeyEvent(keyCode, countX + 1, countY, matrix, FocusLogic.PIVOT, newPageIndex, pageCount, Utilities.isRtl(v.getResources())); - newIcon = parent.getChildAt(newIconIndex); + if (newIconIndex == FocusLogic.NEXT_PAGE_FIRST_ITEM) { + newIcon = handleNextPageFirstItem(workspace, hotseatLayout, pageIndex, + isRtl); + } else if (newIconIndex == FocusLogic.PREVIOUS_PAGE_LAST_ITEM) { + newIcon = handlePreviousPageLastItem(workspace, hotseatLayout, pageIndex, + isRtl); + } else { + newIcon = parent.getChildAt(newIconIndex); + } } break; case FocusLogic.PREVIOUS_PAGE_FIRST_ITEM: - parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1); - newIcon = parent.getChildAt(0); + workspaceLayout = (CellLayout) workspace.getChildAt(pageIndex - 1); + newIcon = getFirstFocusableIconInReadingOrder(workspaceLayout, isRtl); + if (newIcon == null) { + newIcon = getFirstFocusableIconInReadingOrder(hotseatLayout, isRtl); + workspace.snapToPage(pageIndex - 1); + } break; case FocusLogic.PREVIOUS_PAGE_LAST_ITEM: - parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1); - newIcon = parent.getChildAt(parent.getChildCount() - 1); + newIcon = handlePreviousPageLastItem(workspace, hotseatLayout, pageIndex, isRtl); break; case FocusLogic.NEXT_PAGE_FIRST_ITEM: - parent = getCellLayoutChildrenForIndex(workspace, pageIndex + 1); - newIcon = parent.getChildAt(0); + newIcon = handleNextPageFirstItem(workspace, hotseatLayout, pageIndex, isRtl); break; case FocusLogic.NEXT_PAGE_LEFT_COLUMN: case FocusLogic.PREVIOUS_PAGE_LEFT_COLUMN: @@ -425,14 +437,28 @@ public class FocusHelper { newIconIndex = FocusLogic.handleKeyEvent(keyCode, countX + 1, countY, matrix, FocusLogic.PIVOT, newPageIndex, pageCount, Utilities.isRtl(v.getResources())); - newIcon = parent.getChildAt(newIconIndex); + if (newIconIndex == FocusLogic.NEXT_PAGE_FIRST_ITEM) { + newIcon = handleNextPageFirstItem(workspace, hotseatLayout, pageIndex, + isRtl); + } else if (newIconIndex == FocusLogic.PREVIOUS_PAGE_LAST_ITEM) { + newIcon = handlePreviousPageLastItem(workspace, hotseatLayout, pageIndex, + isRtl); + } else { + newIcon = parent.getChildAt(newIconIndex); + } } break; case FocusLogic.CURRENT_PAGE_FIRST_ITEM: - newIcon = parent.getChildAt(0); + newIcon = getFirstFocusableIconInReadingOrder(workspaceLayout, isRtl); + if (newIcon == null) { + newIcon = getFirstFocusableIconInReadingOrder(hotseatLayout, isRtl); + } break; case FocusLogic.CURRENT_PAGE_LAST_ITEM: - newIcon = parent.getChildAt(parent.getChildCount() - 1); + newIcon = getFirstFocusableIconInReverseReadingOrder(workspaceLayout, isRtl); + if (newIcon == null) { + newIcon = getFirstFocusableIconInReverseReadingOrder(hotseatLayout, isRtl); + } break; default: // current page, some item. @@ -507,4 +533,55 @@ public class FocusHelper { return (keyCode == KeyEvent.KEYCODE_DEL || keyCode == KeyEvent.KEYCODE_FORWARD_DEL) && event.hasModifiers(KeyEvent.META_CTRL_ON); } + + private static View handlePreviousPageLastItem(Workspace workspace, CellLayout hotseatLayout, + int pageIndex, boolean isRtl) { + CellLayout workspaceLayout = (CellLayout) workspace.getChildAt(pageIndex - 1); + View newIcon = getFirstFocusableIconInReverseReadingOrder(workspaceLayout, isRtl); + if (newIcon == null) { + newIcon = getFirstFocusableIconInReverseReadingOrder(hotseatLayout,isRtl); + workspace.snapToPage(pageIndex - 1); + } + return newIcon; + } + + private static View handleNextPageFirstItem(Workspace workspace, CellLayout hotseatLayout, + int pageIndex, boolean isRtl) { + CellLayout workspaceLayout = (CellLayout) workspace.getChildAt(pageIndex + 1); + View newIcon = getFirstFocusableIconInReadingOrder(workspaceLayout, isRtl); + if (newIcon == null) { + newIcon = getFirstFocusableIconInReadingOrder(hotseatLayout, isRtl); + workspace.snapToPage(pageIndex + 1); + } + return newIcon; + } + + private static View getFirstFocusableIconInReadingOrder(CellLayout cellLayout, boolean isRtl) { + View icon; + int countX = cellLayout.getCountX(); + for (int y = 0; y < cellLayout.getCountY(); y++) { + int increment = isRtl ? -1 : 1; + for (int x = isRtl ? countX - 1 : 0; 0 <= x && x < countX; x += increment) { + if ((icon = cellLayout.getChildAt(x, y)) != null && icon.isFocusable()) { + return icon; + } + } + } + return null; + } + + private static View getFirstFocusableIconInReverseReadingOrder(CellLayout cellLayout, + boolean isRtl) { + View icon; + int countX = cellLayout.getCountX(); + for (int y = cellLayout.getCountY() - 1; y >= 0; y--) { + int increment = isRtl ? 1 : -1; + for (int x = isRtl ? 0 : countX - 1; 0 <= x && x < countX; x += increment) { + if ((icon = cellLayout.getChildAt(x, y)) != null && icon.isFocusable()) { + return icon; + } + } + } + return null; + } } -- cgit v1.2.3