diff options
-rw-r--r-- | src/com/android/launcher3/FocusHelper.java | 97 | ||||
-rw-r--r-- | src/com/android/launcher3/util/FocusLogic.java | 20 | ||||
-rw-r--r-- | tests/src/com/android/launcher3/util/FocusLogicTest.java | 2 |
3 files changed, 96 insertions, 23 deletions
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; + } } diff --git a/src/com/android/launcher3/util/FocusLogic.java b/src/com/android/launcher3/util/FocusLogic.java index f56d16222..22e0cadea 100644 --- a/src/com/android/launcher3/util/FocusLogic.java +++ b/src/com/android/launcher3/util/FocusLogic.java @@ -92,7 +92,7 @@ public class FocusLogic { int newIndex = NOOP; switch (keyCode) { case KeyEvent.KEYCODE_DPAD_LEFT: - newIndex = handleDpadHorizontal(iconIdx, cntX, cntY, map, -1 /*increment*/); + newIndex = handleDpadHorizontal(iconIdx, cntX, cntY, map, -1 /*increment*/, isRtl); if (!isRtl && newIndex == NOOP && pageIndex > 0) { newIndex = PREVIOUS_PAGE_RIGHT_COLUMN; } else if (isRtl && newIndex == NOOP && pageIndex < pageCount - 1) { @@ -100,7 +100,7 @@ public class FocusLogic { } break; case KeyEvent.KEYCODE_DPAD_RIGHT: - newIndex = handleDpadHorizontal(iconIdx, cntX, cntY, map, 1 /*increment*/); + newIndex = handleDpadHorizontal(iconIdx, cntX, cntY, map, 1 /*increment*/, isRtl); if (!isRtl && newIndex == NOOP && pageIndex < pageCount - 1) { newIndex = NEXT_PAGE_LEFT_COLUMN; } else if (isRtl && newIndex == NOOP && pageIndex > 0) { @@ -314,7 +314,7 @@ public class FocusLogic { */ // TODO: add unit tests to verify all permutation. private static int handleDpadHorizontal(int iconIdx, int cntX, int cntY, - int[][] matrix, int increment) { + int[][] matrix, int increment, boolean isRtl) { if(matrix == null) { throw new IllegalStateException("Dpad navigation requires a matrix."); } @@ -370,17 +370,13 @@ public class FocusLogic { } } - // Rule 3: if switching between pages, do a brute-force search to find an item that was - // missed by rules 1 and 2 (such as when going from a bottom right icon to top left) + // Rule3: if switching between pages, do a brute-force search to find an item that was + // missed by rules 1 and 2 (such as when going from a bottom right icon to top left) if (iconIdx == PIVOT) { - for (x = xPos + increment; 0 <= x && x < cntX; x += increment) { - for (int y = 0; y < cntY; y++) { - if ((newIconIndex = inspectMatrix(x, y, cntX, cntY, matrix)) != NOOP - && newIconIndex != ALL_APPS_COLUMN) { - return newIconIndex; - } - } + if (isRtl) { + return increment < 0 ? NEXT_PAGE_FIRST_ITEM : PREVIOUS_PAGE_LAST_ITEM; } + return increment < 0 ? PREVIOUS_PAGE_LAST_ITEM : NEXT_PAGE_FIRST_ITEM; } return newIconIndex; } diff --git a/tests/src/com/android/launcher3/util/FocusLogicTest.java b/tests/src/com/android/launcher3/util/FocusLogicTest.java index f93e91313..ee2442755 100644 --- a/tests/src/com/android/launcher3/util/FocusLogicTest.java +++ b/tests/src/com/android/launcher3/util/FocusLogicTest.java @@ -80,7 +80,7 @@ public final class FocusLogicTest extends AndroidTestCase { {100, -1, -1, -1, -1, -1}, }); int i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_RIGHT, 6, 5, map, 100, 1, 2, false); - assertEquals(0, i); + assertEquals(FocusLogic.NEXT_PAGE_FIRST_ITEM, i); } public void testMoveIntoHotseatWithEqualHotseatAndWorkspaceColumns() { |