[key event focus handling] (1)hotseat <-> icon now symmetric, (2)support DEL keycode
TL;DR; (1) Key event navigation from and to the hotseat and icons in the workspace is now symmetric. Since there is one more icon in the hotseat, only left N-1 icon navigation was symmetric. (2) KeyEvent.KEYCODE_DEL and KeyEvent.KEYCODE_FORWARD_DEL can now delete icons from the workspace. The focus move to the previous icon where the focus traveled from. Also contains minor styling and indexing issues. Bug: 15408321 Bug: 19381790 Change-Id: I16cbcb2693e92eebb830997d01c0bf674073dd51
This commit is contained in:
@@ -170,54 +170,68 @@ public class FocusHelper {
|
||||
// Initialize the variables.
|
||||
final ShortcutAndWidgetContainer hotseatParent = (ShortcutAndWidgetContainer) v.getParent();
|
||||
final CellLayout hotseatLayout = (CellLayout) hotseatParent.getParent();
|
||||
Hotseat hotseat = (Hotseat) hotseatLayout.getParent();
|
||||
|
||||
Workspace workspace = (Workspace) v.getRootView().findViewById(R.id.workspace);
|
||||
int pageIndex = workspace.getCurrentPage();
|
||||
int pageCount = workspace.getChildCount();
|
||||
int countX, countY;
|
||||
int countX = -1;
|
||||
int countY = -1;
|
||||
int iconIndex = findIndexOfView(hotseatParent, v);
|
||||
|
||||
final CellLayout iconLayout = (CellLayout) workspace.getChildAt(pageIndex);
|
||||
final ViewGroup iconParent = iconLayout.getShortcutsAndWidgets();
|
||||
|
||||
ViewGroup parent = null;
|
||||
int[][] matrix;
|
||||
int[][] matrix = null;
|
||||
|
||||
if (keyCode == KeyEvent.KEYCODE_DPAD_UP &&
|
||||
orientation == Configuration.ORIENTATION_PORTRAIT) {
|
||||
matrix = FocusLogic.createSparseMatrix(iconLayout, hotseatLayout, orientation);
|
||||
// TODO: hotseat indexing should be symmetric.
|
||||
matrix = FocusLogic.createSparseMatrix(iconLayout, hotseatLayout, orientation,
|
||||
hotseat.getAllAppsButtonRank(), true /* include all apps icon */);
|
||||
iconIndex += iconParent.getChildCount();
|
||||
countX = iconLayout.getCountX();
|
||||
countY = iconLayout.getCountY() + hotseatLayout.getCountY();
|
||||
parent = iconParent;
|
||||
} else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT &&
|
||||
orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
matrix = FocusLogic.createSparseMatrix(iconLayout, hotseatLayout, orientation);
|
||||
// TODO: hotseat indexing should be symmetric.
|
||||
matrix = FocusLogic.createSparseMatrix(iconLayout, hotseatLayout, orientation,
|
||||
hotseat.getAllAppsButtonRank(), true /* include all apps icon */);
|
||||
iconIndex += iconParent.getChildCount();
|
||||
countX = iconLayout.getCountX() + hotseatLayout.getCountX();
|
||||
countY = iconLayout.getCountY();
|
||||
parent = iconParent;
|
||||
} else {
|
||||
} else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT &&
|
||||
orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
keyCode = KeyEvent.KEYCODE_PAGE_DOWN;
|
||||
}else {
|
||||
// For other KEYCODE_DPAD_LEFT and KEYCODE_DPAD_RIGHT navigation, do not use the
|
||||
// matrix extended with hotseat.
|
||||
matrix = FocusLogic.createSparseMatrix(hotseatLayout);
|
||||
parent = hotseatParent;
|
||||
countX = hotseatLayout.getCountX();
|
||||
countY = hotseatLayout.getCountY();
|
||||
|
||||
parent = hotseatParent;
|
||||
}
|
||||
|
||||
// Process the focus.
|
||||
int newIconIndex = FocusLogic.handleKeyEvent(keyCode, countX, countY, matrix,
|
||||
iconIndex, pageIndex, pageCount);
|
||||
|
||||
if (iconParent.getChildCount() <= newIconIndex &&
|
||||
newIconIndex < iconParent.getChildCount() + hotseatParent.getChildCount()) {
|
||||
View newIcon = null;
|
||||
if (newIconIndex == FocusLogic.NEXT_PAGE_FIRST_ITEM) {
|
||||
parent = getCellLayoutChildrenForIndex(workspace, pageIndex + 1);
|
||||
newIcon = parent.getChildAt(0);
|
||||
// TODO(hyunyoungs): handle cases where the child is not an icon but
|
||||
// a folder or a widget.
|
||||
workspace.snapToPage(pageIndex + 1);
|
||||
}
|
||||
if (parent == iconParent && newIconIndex >= iconParent.getChildCount()) {
|
||||
newIconIndex -= iconParent.getChildCount();
|
||||
}
|
||||
if (parent != null) {
|
||||
View newIcon = parent.getChildAt(newIconIndex);
|
||||
if (newIcon == null && newIconIndex >=0) {
|
||||
newIcon = parent.getChildAt(newIconIndex);
|
||||
}
|
||||
if (newIcon != null) {
|
||||
newIcon.requestFocus();
|
||||
playSoundEffect(keyCode, v);
|
||||
@@ -242,34 +256,39 @@ public class FocusHelper {
|
||||
|
||||
// Initialize the variables.
|
||||
ShortcutAndWidgetContainer parent = (ShortcutAndWidgetContainer) v.getParent();
|
||||
final CellLayout layout = (CellLayout) parent.getParent();
|
||||
final Workspace workspace = (Workspace) layout.getParent();
|
||||
final CellLayout iconLayout = (CellLayout) parent.getParent();
|
||||
final Workspace workspace = (Workspace) iconLayout.getParent();
|
||||
final ViewGroup launcher = (ViewGroup) workspace.getParent();
|
||||
final ViewGroup tabs = (ViewGroup) launcher.findViewById(R.id.search_drop_target_bar);
|
||||
final ViewGroup hotseat = (ViewGroup) launcher.findViewById(R.id.hotseat);
|
||||
int pageIndex = workspace.indexOfChild(layout);
|
||||
final Hotseat hotseat = (Hotseat) launcher.findViewById(R.id.hotseat);
|
||||
int pageIndex = workspace.indexOfChild(iconLayout);
|
||||
int pageCount = workspace.getChildCount();
|
||||
final int countX = layout.getCountX();
|
||||
int countY = layout.getCountY();
|
||||
int countX = iconLayout.getCountX();
|
||||
int countY = iconLayout.getCountY();
|
||||
final int iconIndex = findIndexOfView(parent, v);
|
||||
|
||||
CellLayout hotseatLayout = (CellLayout) hotseat.getChildAt(0);
|
||||
ShortcutAndWidgetContainer hotseatParent = hotseatLayout.getShortcutsAndWidgets();
|
||||
int[][] matrix;
|
||||
|
||||
// KEYCODE_DPAD_DOWN in portrait (KEYCODE_DPAD_LEFT in landscape) is the only key allowed
|
||||
// KEYCODE_DPAD_DOWN in portrait (KEYCODE_DPAD_RIGHT in landscape) is the only key allowed
|
||||
// to take a user to the hotseat. For other dpad navigation, do not use the matrix extended
|
||||
// with the hotseat.
|
||||
if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN &&
|
||||
orientation == Configuration.ORIENTATION_PORTRAIT) {
|
||||
matrix = FocusLogic.createSparseMatrix(layout, hotseatLayout, orientation);
|
||||
matrix = FocusLogic.createSparseMatrix(iconLayout, hotseatLayout, orientation,
|
||||
hotseat.getAllAppsButtonRank(), false /* all apps icon is ignored */);
|
||||
countY = countY + 1;
|
||||
} else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT &&
|
||||
} else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT &&
|
||||
orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
matrix = FocusLogic.createSparseMatrix(layout, hotseatLayout, orientation);
|
||||
countY = countY + 1;
|
||||
matrix = FocusLogic.createSparseMatrix(iconLayout, hotseatLayout, orientation,
|
||||
hotseat.getAllAppsButtonRank(), false /* all apps icon is ignored */);
|
||||
countX = countX + 1;
|
||||
} else if (keyCode == KeyEvent.KEYCODE_DEL || keyCode == KeyEvent.KEYCODE_FORWARD_DEL) {
|
||||
workspace.removeWorkspaceItem(v);
|
||||
return consume;
|
||||
} else {
|
||||
matrix = FocusLogic.createSparseMatrix(layout);
|
||||
matrix = FocusLogic.createSparseMatrix(iconLayout);
|
||||
}
|
||||
|
||||
// Process the focus.
|
||||
@@ -294,7 +313,7 @@ public class FocusHelper {
|
||||
case FocusLogic.NEXT_PAGE_FIRST_ITEM:
|
||||
parent = getCellLayoutChildrenForIndex(workspace, pageIndex + 1);
|
||||
newIcon = parent.getChildAt(0);
|
||||
workspace.snapToPage(pageIndex - 1);
|
||||
workspace.snapToPage(pageIndex + 1);
|
||||
break;
|
||||
case FocusLogic.CURRENT_PAGE_FIRST_ITEM:
|
||||
newIcon = parent.getChildAt(0);
|
||||
@@ -344,8 +363,7 @@ public class FocusHelper {
|
||||
final int iconIndex = findIndexOfView(parent, v);
|
||||
int pageIndex = workspace.indexOfChild(layout);
|
||||
int pageCount = workspace.getChildCount();
|
||||
int[][] map = FocusLogic.createFullMatrix(countX, countY, true /* incremental order index */
|
||||
);
|
||||
int[][] map = FocusLogic.createFullMatrix(countX, countY, true /* incremental order */);
|
||||
|
||||
// Process the focus.
|
||||
int newIconIndex = FocusLogic.handleKeyEvent(keyCode, countX, countY, map, iconIndex,
|
||||
|
||||
@@ -83,13 +83,24 @@ public class Hotseat extends FrameLayout {
|
||||
int getOrderInHotseat(int x, int y) {
|
||||
return hasVerticalHotseat() ? (mContent.getCountY() - y - 1) : x;
|
||||
}
|
||||
|
||||
/* Get the orientation specific coordinates given an invariant order in the hotseat. */
|
||||
int getCellXFromOrder(int rank) {
|
||||
return hasVerticalHotseat() ? 0 : rank;
|
||||
}
|
||||
|
||||
int getCellYFromOrder(int rank) {
|
||||
return hasVerticalHotseat() ? (mContent.getCountY() - (rank + 1)) : 0;
|
||||
}
|
||||
|
||||
public int getAllAppsButtonRank() {
|
||||
if (LauncherAppState.isDisableAllApps()) {
|
||||
return -1;
|
||||
} else {
|
||||
return mAllAppsButtonRank;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAllAppsButtonRank(int rank) {
|
||||
if (LauncherAppState.isDisableAllApps()) {
|
||||
return false;
|
||||
|
||||
@@ -4231,6 +4231,9 @@ public class Workspace extends SmoothPagedView
|
||||
mDragInfo = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* For opposite operation. See {@link #addInScreen}.
|
||||
*/
|
||||
public void removeWorkspaceItem(View v) {
|
||||
CellLayout parentCell = getParentCellLayoutForView(v);
|
||||
if (parentCell != null) {
|
||||
|
||||
@@ -47,10 +47,13 @@ public class FocusLogic {
|
||||
|
||||
// Item and page index related constant used by {@link #handleKeyEvent}.
|
||||
public static final int NOOP = -1;
|
||||
|
||||
public static final int PREVIOUS_PAGE_FIRST_ITEM = -2;
|
||||
public static final int PREVIOUS_PAGE_LAST_ITEM = -3;
|
||||
|
||||
public static final int CURRENT_PAGE_FIRST_ITEM = -4;
|
||||
public static final int CURRENT_PAGE_LAST_ITEM = -5;
|
||||
|
||||
public static final int NEXT_PAGE_FIRST_ITEM = -6;
|
||||
|
||||
// Matrix related constant.
|
||||
@@ -63,7 +66,8 @@ public class FocusLogic {
|
||||
if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT ||
|
||||
keyCode == KeyEvent.KEYCODE_DPAD_UP || keyCode == KeyEvent.KEYCODE_DPAD_DOWN ||
|
||||
keyCode == KeyEvent.KEYCODE_MOVE_HOME || keyCode == KeyEvent.KEYCODE_MOVE_END ||
|
||||
keyCode == KeyEvent.KEYCODE_PAGE_UP || keyCode == KeyEvent.KEYCODE_PAGE_DOWN) {
|
||||
keyCode == KeyEvent.KEYCODE_PAGE_UP || keyCode == KeyEvent.KEYCODE_PAGE_DOWN ||
|
||||
keyCode == KeyEvent.KEYCODE_DEL || keyCode == KeyEvent.KEYCODE_FORWARD_DEL) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -175,9 +179,9 @@ public class FocusLogic {
|
||||
* The size of the returning matrix is [icon column count x (icon + hotseat row count)]
|
||||
* in portrait orientation. In landscape, [(icon + hotseat) column count x (icon row count)]
|
||||
*/
|
||||
// TODO: get rid of the dynamic matrix creation
|
||||
// TODO: get rid of the dynamic matrix creation
|
||||
public static int[][] createSparseMatrix(CellLayout iconLayout, CellLayout hotseatLayout,
|
||||
int orientation) {
|
||||
int orientation, int allappsiconRank, boolean includeAllappsicon) {
|
||||
|
||||
ViewGroup iconParent = iconLayout.getShortcutsAndWidgets();
|
||||
ViewGroup hotseatParent = hotseatLayout.getShortcutsAndWidgets();
|
||||
@@ -203,22 +207,27 @@ public class FocusLogic {
|
||||
}
|
||||
|
||||
// Iterate thru the children of the bottom parent
|
||||
for(int i = 0; i < hotseatParent.getChildCount(); i++) {
|
||||
// If the hotseat view group contains more items than topColumnCnt, then just
|
||||
// discard them.
|
||||
// TODO: make this more elegant. (look at DynamicGrid)
|
||||
// The hotseat view group contains one more item than iconLayout column count.
|
||||
// If {@param allappsiconRank} not negative, then the last icon in the hotseat
|
||||
// is truncated. If it is negative, then all apps icon index is not inserted.
|
||||
for(int i = hotseatParent.getChildCount() - 1; i >= (includeAllappsicon ? 0 : 1); i--) {
|
||||
int delta = 0;
|
||||
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
|
||||
int cx = ((CellLayout.LayoutParams)
|
||||
hotseatParent.getChildAt(i).getLayoutParams()).cellX;
|
||||
if (cx < iconLayout.getCountX()) {
|
||||
matrix[cx][iconLayout.getCountY()] = iconParent.getChildCount() + i;
|
||||
if ((includeAllappsicon && cx >= allappsiconRank) ||
|
||||
(!includeAllappsicon && cx > allappsiconRank)) {
|
||||
delta = -1;
|
||||
}
|
||||
matrix[cx + delta][iconLayout.getCountY()] = iconParent.getChildCount() + i;
|
||||
} else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
int cy = ((CellLayout.LayoutParams)
|
||||
hotseatParent.getChildAt(i).getLayoutParams()).cellY;
|
||||
if (cy < iconLayout.getCountY()) {
|
||||
matrix[iconLayout.getCountX()][cy] = iconParent.getChildCount() + i;
|
||||
if ((includeAllappsicon && cy >= allappsiconRank) ||
|
||||
(!includeAllappsicon && cy > allappsiconRank)) {
|
||||
delta = -1;
|
||||
}
|
||||
matrix[iconLayout.getCountX()][cy + delta] = iconParent.getChildCount() + i;
|
||||
}
|
||||
}
|
||||
if (DEBUG) {
|
||||
@@ -266,12 +275,7 @@ public class FocusLogic {
|
||||
|
||||
// Rule1: check first in the horizontal direction
|
||||
for (int i = xPos + increment; 0 <= i && i < cntX; i = i + increment) {
|
||||
if (DEBUG) {
|
||||
Log.v(TAG, String.format("\t\tsearch: \t[x, y]=[%d, %d] iconIndex=%d",
|
||||
i, yPos, matrix[i][yPos]));
|
||||
}
|
||||
if (matrix[i][yPos] != -1) {
|
||||
newIconIndex = matrix[i][yPos];
|
||||
if ((newIconIndex = inspectMatrix(i, yPos, cntX, cntY, matrix)) != NOOP) {
|
||||
return newIconIndex;
|
||||
}
|
||||
}
|
||||
@@ -332,12 +336,7 @@ public class FocusLogic {
|
||||
|
||||
// Rule1: check first in the dpad direction
|
||||
for (int j = yPos + increment; 0 <= j && j <cntY && 0 <= j; j = j + increment) {
|
||||
if (DEBUG) {
|
||||
Log.v(TAG, String.format("\t\tsearch: \t[x, y]=[%d, %d] iconIndex=%d",
|
||||
xPos, j, matrix[xPos][j]));
|
||||
}
|
||||
if (matrix[xPos][j] != -1) {
|
||||
newIconIndex = matrix[xPos][j];
|
||||
if ((newIconIndex = inspectMatrix(xPos, j, cntX, cntY, matrix)) != NOOP) {
|
||||
return newIconIndex;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user