Merge "[key event focus] DPAD navigates to the nearest item on next/previous page b/19381790 b/16351792" into ub-launcher3-burnaby
This commit is contained in:
committed by
Android (Google) Code Review
commit
cbd02cefc8
@@ -89,6 +89,7 @@ public class FocusHelper {
|
|||||||
countX = ((CellLayout) parentLayout).getCountX();
|
countX = ((CellLayout) parentLayout).getCountX();
|
||||||
countY = ((CellLayout) parentLayout).getCountY();
|
countY = ((CellLayout) parentLayout).getCountY();
|
||||||
} else if (v.getParent() instanceof ViewGroup) {
|
} else if (v.getParent() instanceof ViewGroup) {
|
||||||
|
//TODO(hyunyoungs): figure out when this needs to be called.
|
||||||
itemContainer = parentLayout = (ViewGroup) v.getParent();
|
itemContainer = parentLayout = (ViewGroup) v.getParent();
|
||||||
countX = ((PagedViewGridLayout) parentLayout).getCellCountX();
|
countX = ((PagedViewGridLayout) parentLayout).getCellCountX();
|
||||||
countY = ((PagedViewGridLayout) parentLayout).getCellCountY();
|
countY = ((PagedViewGridLayout) parentLayout).getCellCountY();
|
||||||
@@ -102,6 +103,7 @@ public class FocusHelper {
|
|||||||
final int pageCount = container.getChildCount();
|
final int pageCount = container.getChildCount();
|
||||||
ViewGroup newParent = null;
|
ViewGroup newParent = null;
|
||||||
View child = null;
|
View child = null;
|
||||||
|
// TODO(hyunyoungs): this matrix is not applicable on the last page.
|
||||||
int[][] matrix = FocusLogic.createFullMatrix(countX, countY, true);
|
int[][] matrix = FocusLogic.createFullMatrix(countX, countY, true);
|
||||||
|
|
||||||
// Process focus.
|
// Process focus.
|
||||||
@@ -111,12 +113,22 @@ public class FocusHelper {
|
|||||||
return consume;
|
return consume;
|
||||||
}
|
}
|
||||||
switch (newIconIndex) {
|
switch (newIconIndex) {
|
||||||
|
case FocusLogic.PREVIOUS_PAGE_RIGHT_COLUMN:
|
||||||
|
newParent = getAppsCustomizePage(container, pageIndex -1);
|
||||||
|
if (newParent != null) {
|
||||||
|
int row = FocusLogic.findRow(matrix, iconIndex);
|
||||||
|
container.snapToPage(pageIndex - 1);
|
||||||
|
// no need to create a new matrix.
|
||||||
|
child = newParent.getChildAt(matrix[countX-1][row]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case FocusLogic.PREVIOUS_PAGE_FIRST_ITEM:
|
case FocusLogic.PREVIOUS_PAGE_FIRST_ITEM:
|
||||||
newParent = getAppsCustomizePage(container, pageIndex - 1);
|
newParent = getAppsCustomizePage(container, pageIndex - 1);
|
||||||
if (newParent != null) {
|
if (newParent != null) {
|
||||||
container.snapToPage(pageIndex - 1);
|
container.snapToPage(pageIndex - 1);
|
||||||
child = newParent.getChildAt(0);
|
child = newParent.getChildAt(0);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
case FocusLogic.PREVIOUS_PAGE_LAST_ITEM:
|
case FocusLogic.PREVIOUS_PAGE_LAST_ITEM:
|
||||||
newParent = getAppsCustomizePage(container, pageIndex - 1);
|
newParent = getAppsCustomizePage(container, pageIndex - 1);
|
||||||
if (newParent != null) {
|
if (newParent != null) {
|
||||||
@@ -131,6 +143,14 @@ public class FocusHelper {
|
|||||||
child = newParent.getChildAt(0);
|
child = newParent.getChildAt(0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case FocusLogic.NEXT_PAGE_LEFT_COLUMN:
|
||||||
|
newParent = getAppsCustomizePage(container, pageIndex + 1);
|
||||||
|
if (newParent != null) {
|
||||||
|
container.snapToPage(pageIndex + 1);
|
||||||
|
int row = FocusLogic.findRow(matrix, iconIndex);
|
||||||
|
child = newParent.getChildAt(matrix[0][row]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case FocusLogic.CURRENT_PAGE_FIRST_ITEM:
|
case FocusLogic.CURRENT_PAGE_FIRST_ITEM:
|
||||||
child = container.getChildAt(0);
|
child = container.getChildAt(0);
|
||||||
break;
|
break;
|
||||||
@@ -256,7 +276,7 @@ public class FocusHelper {
|
|||||||
|
|
||||||
// Initialize the variables.
|
// Initialize the variables.
|
||||||
ShortcutAndWidgetContainer parent = (ShortcutAndWidgetContainer) v.getParent();
|
ShortcutAndWidgetContainer parent = (ShortcutAndWidgetContainer) v.getParent();
|
||||||
final CellLayout iconLayout = (CellLayout) parent.getParent();
|
CellLayout iconLayout = (CellLayout) parent.getParent();
|
||||||
final Workspace workspace = (Workspace) iconLayout.getParent();
|
final Workspace workspace = (Workspace) iconLayout.getParent();
|
||||||
final ViewGroup launcher = (ViewGroup) workspace.getParent();
|
final ViewGroup launcher = (ViewGroup) workspace.getParent();
|
||||||
final ViewGroup tabs = (ViewGroup) launcher.findViewById(R.id.search_drop_target_bar);
|
final ViewGroup tabs = (ViewGroup) launcher.findViewById(R.id.search_drop_target_bar);
|
||||||
@@ -301,10 +321,23 @@ public class FocusHelper {
|
|||||||
newIcon = tabs;
|
newIcon = tabs;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case FocusLogic.PREVIOUS_PAGE_RIGHT_COLUMN:
|
||||||
|
int row = FocusLogic.findRow(matrix, iconIndex);
|
||||||
|
parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
|
||||||
|
if (parent != null) {
|
||||||
|
iconLayout = (CellLayout) parent.getParent();
|
||||||
|
matrix = FocusLogic.createSparseMatrix(iconLayout, orientation,
|
||||||
|
iconLayout.getCountX(), row);
|
||||||
|
newIconIndex = FocusLogic.handleKeyEvent(keyCode, countX + 1, countY, matrix,
|
||||||
|
FocusLogic.PIVOT, pageIndex - 1, pageCount);
|
||||||
|
newIcon = parent.getChildAt(newIconIndex);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case FocusLogic.PREVIOUS_PAGE_FIRST_ITEM:
|
case FocusLogic.PREVIOUS_PAGE_FIRST_ITEM:
|
||||||
parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
|
parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
|
||||||
newIcon = parent.getChildAt(0);
|
newIcon = parent.getChildAt(0);
|
||||||
workspace.snapToPage(pageIndex - 1);
|
workspace.snapToPage(pageIndex - 1);
|
||||||
|
break;
|
||||||
case FocusLogic.PREVIOUS_PAGE_LAST_ITEM:
|
case FocusLogic.PREVIOUS_PAGE_LAST_ITEM:
|
||||||
parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
|
parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
|
||||||
newIcon = parent.getChildAt(parent.getChildCount() - 1);
|
newIcon = parent.getChildAt(parent.getChildCount() - 1);
|
||||||
@@ -315,6 +348,17 @@ public class FocusHelper {
|
|||||||
newIcon = parent.getChildAt(0);
|
newIcon = parent.getChildAt(0);
|
||||||
workspace.snapToPage(pageIndex + 1);
|
workspace.snapToPage(pageIndex + 1);
|
||||||
break;
|
break;
|
||||||
|
case FocusLogic.NEXT_PAGE_LEFT_COLUMN:
|
||||||
|
row = FocusLogic.findRow(matrix, iconIndex);
|
||||||
|
parent = getCellLayoutChildrenForIndex(workspace, pageIndex + 1);
|
||||||
|
if (parent != null) {
|
||||||
|
iconLayout = (CellLayout) parent.getParent();
|
||||||
|
matrix = FocusLogic.createSparseMatrix(iconLayout, orientation, -1, row);
|
||||||
|
newIconIndex = FocusLogic.handleKeyEvent(keyCode, countX + 1, countY, matrix,
|
||||||
|
FocusLogic.PIVOT, pageIndex, pageCount);
|
||||||
|
newIcon = parent.getChildAt(newIconIndex);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case FocusLogic.CURRENT_PAGE_FIRST_ITEM:
|
case FocusLogic.CURRENT_PAGE_FIRST_ITEM:
|
||||||
newIcon = parent.getChildAt(0);
|
newIcon = parent.getChildAt(0);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -48,16 +48,19 @@ public class FocusLogic {
|
|||||||
// Item and page index related constant used by {@link #handleKeyEvent}.
|
// Item and page index related constant used by {@link #handleKeyEvent}.
|
||||||
public static final int NOOP = -1;
|
public static final int NOOP = -1;
|
||||||
|
|
||||||
public static final int PREVIOUS_PAGE_FIRST_ITEM = -2;
|
public static final int PREVIOUS_PAGE_RIGHT_COLUMN = -2;
|
||||||
public static final int PREVIOUS_PAGE_LAST_ITEM = -3;
|
public static final int PREVIOUS_PAGE_FIRST_ITEM = -3;
|
||||||
|
public static final int PREVIOUS_PAGE_LAST_ITEM = -4;
|
||||||
|
|
||||||
public static final int CURRENT_PAGE_FIRST_ITEM = -4;
|
public static final int CURRENT_PAGE_FIRST_ITEM = -5;
|
||||||
public static final int CURRENT_PAGE_LAST_ITEM = -5;
|
public static final int CURRENT_PAGE_LAST_ITEM = -6;
|
||||||
|
|
||||||
public static final int NEXT_PAGE_FIRST_ITEM = -6;
|
public static final int NEXT_PAGE_FIRST_ITEM = -7;
|
||||||
|
public static final int NEXT_PAGE_LEFT_COLUMN = -8;
|
||||||
|
|
||||||
// Matrix related constant.
|
// Matrix related constant.
|
||||||
public static final int EMPTY = -1;
|
public static final int EMPTY = -1;
|
||||||
|
public static final int PIVOT = 100;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true only if this utility class handles the key code.
|
* Returns true only if this utility class handles the key code.
|
||||||
@@ -87,13 +90,13 @@ public class FocusLogic {
|
|||||||
case KeyEvent.KEYCODE_DPAD_LEFT:
|
case KeyEvent.KEYCODE_DPAD_LEFT:
|
||||||
newIndex = handleDpadHorizontal(iconIdx, cntX, cntY, map, -1 /*increment*/);
|
newIndex = handleDpadHorizontal(iconIdx, cntX, cntY, map, -1 /*increment*/);
|
||||||
if (newIndex == NOOP && pageIndex > 0) {
|
if (newIndex == NOOP && pageIndex > 0) {
|
||||||
return PREVIOUS_PAGE_LAST_ITEM;
|
newIndex = PREVIOUS_PAGE_RIGHT_COLUMN;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KeyEvent.KEYCODE_DPAD_RIGHT:
|
case KeyEvent.KEYCODE_DPAD_RIGHT:
|
||||||
newIndex = handleDpadHorizontal(iconIdx, cntX, cntY, map, 1 /*increment*/);
|
newIndex = handleDpadHorizontal(iconIdx, cntX, cntY, map, 1 /*increment*/);
|
||||||
if (newIndex == NOOP && pageIndex < pageCount - 1) {
|
if (newIndex == NOOP && pageIndex < pageCount - 1) {
|
||||||
return NEXT_PAGE_FIRST_ITEM;
|
newIndex = NEXT_PAGE_LEFT_COLUMN;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KeyEvent.KEYCODE_DPAD_DOWN:
|
case KeyEvent.KEYCODE_DPAD_DOWN:
|
||||||
@@ -169,7 +172,7 @@ public class FocusLogic {
|
|||||||
matrix[cx][cy] = i;
|
matrix[cx][cy] = i;
|
||||||
}
|
}
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
printMatrix(matrix, m, n);
|
printMatrix(matrix);
|
||||||
}
|
}
|
||||||
return matrix;
|
return matrix;
|
||||||
}
|
}
|
||||||
@@ -231,7 +234,47 @@ public class FocusLogic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
printMatrix(matrix, m, n);
|
printMatrix(matrix);
|
||||||
|
}
|
||||||
|
return matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a sparse matrix that merges the icon of previous/next page and last column of
|
||||||
|
* current page. When left key is triggered on the leftmost column, sparse matrix is created
|
||||||
|
* that combines previous page matrix and an extra column on the right. Likewise, when right
|
||||||
|
* key is triggered on the rightmost column, sparse matrix is created that combines this column
|
||||||
|
* on the 0th column and the next page matrix.
|
||||||
|
*
|
||||||
|
* @param pivotX x coordinate of the focused item in the current page
|
||||||
|
* @param pivotY y coordinate of the focused item in the current page
|
||||||
|
*/
|
||||||
|
// TODO: get rid of the dynamic matrix creation
|
||||||
|
public static int[][] createSparseMatrix(CellLayout iconLayout, int pivotX, int pivotY) {
|
||||||
|
|
||||||
|
ViewGroup iconParent = iconLayout.getShortcutsAndWidgets();
|
||||||
|
|
||||||
|
int[][] matrix = createFullMatrix(iconLayout.getCountX() + 1, iconLayout.getCountY(),
|
||||||
|
false /* set all cell to empty */);
|
||||||
|
|
||||||
|
// Iterate thru the children of the top parent.
|
||||||
|
for (int i = 0; i < iconParent.getChildCount(); i++) {
|
||||||
|
int cx = ((CellLayout.LayoutParams) iconParent.getChildAt(i).getLayoutParams()).cellX;
|
||||||
|
int cy = ((CellLayout.LayoutParams) iconParent.getChildAt(i).getLayoutParams()).cellY;
|
||||||
|
if (pivotX < 0) {
|
||||||
|
matrix[cx - pivotX][cy] = i;
|
||||||
|
} else {
|
||||||
|
matrix[cx][cy] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pivotX < 0) {
|
||||||
|
matrix[0][pivotY] = PIVOT;
|
||||||
|
} else {
|
||||||
|
matrix[pivotX][pivotY] = PIVOT;
|
||||||
|
}
|
||||||
|
if (DEBUG) {
|
||||||
|
printMatrix(matrix);
|
||||||
}
|
}
|
||||||
return matrix;
|
return matrix;
|
||||||
}
|
}
|
||||||
@@ -407,21 +450,32 @@ public class FocusLogic {
|
|||||||
return newIconIndex;
|
return newIconIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only used for debugging.
|
||||||
|
*/
|
||||||
private static String getStringIndex(int index) {
|
private static String getStringIndex(int index) {
|
||||||
switch(index) {
|
switch(index) {
|
||||||
case NOOP: return "NOOP";
|
case NOOP: return "NOOP";
|
||||||
case PREVIOUS_PAGE_FIRST_ITEM: return "PREVIOUS_PAGE_FIRST";
|
case PREVIOUS_PAGE_FIRST_ITEM: return "PREVIOUS_PAGE_FIRST";
|
||||||
case PREVIOUS_PAGE_LAST_ITEM: return "PREVIOUS_PAGE_LAST";
|
case PREVIOUS_PAGE_LAST_ITEM: return "PREVIOUS_PAGE_LAST";
|
||||||
|
case PREVIOUS_PAGE_RIGHT_COLUMN:return "PREVIOUS_PAGE_RIGHT_COLUMN";
|
||||||
case CURRENT_PAGE_FIRST_ITEM: return "CURRENT_PAGE_FIRST";
|
case CURRENT_PAGE_FIRST_ITEM: return "CURRENT_PAGE_FIRST";
|
||||||
case CURRENT_PAGE_LAST_ITEM: return "CURRENT_PAGE_LAST";
|
case CURRENT_PAGE_LAST_ITEM: return "CURRENT_PAGE_LAST";
|
||||||
case NEXT_PAGE_FIRST_ITEM: return "NEXT_PAGE_FIRST";
|
case NEXT_PAGE_FIRST_ITEM: return "NEXT_PAGE_FIRST";
|
||||||
|
case NEXT_PAGE_LEFT_COLUMN: return "NEXT_PAGE_LEFT_COLUMN";
|
||||||
default:
|
default:
|
||||||
return Integer.toString(index);
|
return Integer.toString(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void printMatrix(int[][] matrix, int m, int n) {
|
/**
|
||||||
|
* Only used for debugging.
|
||||||
|
*/
|
||||||
|
private static void printMatrix(int[][] matrix) {
|
||||||
Log.v(TAG, "\tprintMap:");
|
Log.v(TAG, "\tprintMap:");
|
||||||
|
int m = matrix.length;
|
||||||
|
int n = matrix[0].length;
|
||||||
|
|
||||||
for (int j=0; j < n; j++) {
|
for (int j=0; j < n; j++) {
|
||||||
String colY = "\t\t";
|
String colY = "\t\t";
|
||||||
for (int i=0; i < m; i++) {
|
for (int i=0; i < m; i++) {
|
||||||
@@ -430,4 +484,24 @@ public class FocusLogic {
|
|||||||
Log.v(TAG, colY);
|
Log.v(TAG, colY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Figure out the location of the icon.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
//TODO(hyunyoungs): this helper method should move to CellLayout class while removing the
|
||||||
|
// dynamic matrix creation all together.
|
||||||
|
public static int findRow(int[][] matrix, int iconIndex) {
|
||||||
|
int cntX = matrix.length;
|
||||||
|
int cntY = matrix[0].length;
|
||||||
|
|
||||||
|
for (int i = 0; i < cntX; i++) {
|
||||||
|
for (int j = 0; j < cntY; j++) {
|
||||||
|
if (matrix[i][j] == iconIndex) {
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ package com.android.launcher3;
|
|||||||
|
|
||||||
import android.test.AndroidTestCase;
|
import android.test.AndroidTestCase;
|
||||||
import android.test.suitebuilder.annotation.SmallTest;
|
import android.test.suitebuilder.annotation.SmallTest;
|
||||||
|
import android.view.KeyEvent;
|
||||||
|
|
||||||
|
import com.android.launcher3.util.FocusLogic;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the {@link FocusLogic} class that handles key event based focus handling.
|
* Tests the {@link FocusLogic} class that handles key event based focus handling.
|
||||||
@@ -37,6 +40,21 @@ public final class FocusLogicTest extends AndroidTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testShouldConsume() {
|
public void testShouldConsume() {
|
||||||
// write tests.
|
assertTrue(FocusLogic.shouldConsume(KeyEvent.KEYCODE_DPAD_LEFT));
|
||||||
|
assertTrue(FocusLogic.shouldConsume(KeyEvent.KEYCODE_DPAD_RIGHT));
|
||||||
|
assertTrue(FocusLogic.shouldConsume(KeyEvent.KEYCODE_DPAD_UP));
|
||||||
|
assertTrue(FocusLogic.shouldConsume(KeyEvent.KEYCODE_DPAD_DOWN));
|
||||||
|
assertTrue(FocusLogic.shouldConsume(KeyEvent.KEYCODE_MOVE_HOME));
|
||||||
|
assertTrue(FocusLogic.shouldConsume(KeyEvent.KEYCODE_MOVE_END));
|
||||||
|
assertTrue(FocusLogic.shouldConsume(KeyEvent.KEYCODE_PAGE_UP));
|
||||||
|
assertTrue(FocusLogic.shouldConsume(KeyEvent.KEYCODE_PAGE_DOWN));
|
||||||
|
assertTrue(FocusLogic.shouldConsume(KeyEvent.KEYCODE_DEL));
|
||||||
|
assertTrue(FocusLogic.shouldConsume(KeyEvent.KEYCODE_FORWARD_DEL));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCreateSparseMatrix() {
|
||||||
|
// Either, 1) create a helper method to generate/instantiate all possible cell layout that
|
||||||
|
// may get created in real world to test this method. OR 2) Move all the matrix
|
||||||
|
// management routine to celllayout and write tests for them.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user