Fixing folder focus logic
> Folder items no longer remain in a linear order when a folder gets rearranged, and se we need to use createSparseMatrix instead of createFullArray. Also because of this we need to use getChildAt(x, y) instead of getChildAt(index) > Removing traces of AppsCustomizePage (all apps) from FocusHelper Change-Id: I9007f6b95cb823e27ef4a43ce725fda8ef1b7cf8
This commit is contained in:
@@ -16,14 +16,12 @@
|
||||
|
||||
package com.android.launcher3;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.SoundEffectConstants;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.android.launcher3.FocusHelper.PagedViewKeyListener;
|
||||
import com.android.launcher3.util.FocusLogic;
|
||||
import com.android.launcher3.util.Thunk;
|
||||
|
||||
@@ -52,14 +50,10 @@ public class FocusHelper {
|
||||
private static final String TAG = "FocusHelper";
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
//
|
||||
// Key code handling methods.
|
||||
//
|
||||
|
||||
/**
|
||||
* A keyboard listener for scrollable folders
|
||||
* Handles key events in paged folder.
|
||||
*/
|
||||
public static class PagedFolderKeyEventListener extends PagedViewKeyListener {
|
||||
public static class PagedFolderKeyEventListener implements View.OnKeyListener {
|
||||
|
||||
private final Folder mFolder;
|
||||
|
||||
@@ -67,20 +61,6 @@ public class FocusHelper {
|
||||
mFolder = folder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleNoopKey(int keyCode, View v) {
|
||||
if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
|
||||
mFolder.mFolderName.requestFocus();
|
||||
playSoundEffect(keyCode, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles key events in the all apps screen.
|
||||
*/
|
||||
public static class PagedViewKeyListener implements View.OnKeyListener {
|
||||
|
||||
@Override
|
||||
public boolean onKey(View v, int keyCode, KeyEvent e) {
|
||||
boolean consume = FocusLogic.shouldConsume(keyCode);
|
||||
@@ -88,21 +68,12 @@ public class FocusHelper {
|
||||
return consume;
|
||||
}
|
||||
if (DEBUG) {
|
||||
Log.v(TAG, String.format("Handle ALL APPS and Folders keyevent=[%s].",
|
||||
Log.v(TAG, String.format("Handle ALL Folders keyevent=[%s].",
|
||||
KeyEvent.keyCodeToString(keyCode)));
|
||||
}
|
||||
|
||||
// Initialize variables.
|
||||
ViewGroup parentLayout;
|
||||
ViewGroup itemContainer;
|
||||
int countX;
|
||||
int countY;
|
||||
if (v.getParent() instanceof ShortcutAndWidgetContainer) {
|
||||
itemContainer = (ViewGroup) v.getParent();
|
||||
parentLayout = (ViewGroup) itemContainer.getParent();
|
||||
countX = ((CellLayout) parentLayout).getCountX();
|
||||
countY = ((CellLayout) parentLayout).getCountY();
|
||||
} else {
|
||||
|
||||
if (!(v.getParent() instanceof ShortcutAndWidgetContainer)) {
|
||||
if (LauncherAppState.isDogfoodBuild()) {
|
||||
throw new IllegalStateException("Parent of the focused item is not supported.");
|
||||
} else {
|
||||
@@ -110,15 +81,19 @@ public class FocusHelper {
|
||||
}
|
||||
}
|
||||
|
||||
final int iconIndex = itemContainer.indexOfChild(v);
|
||||
final PagedView container = (PagedView) parentLayout.getParent();
|
||||
final int pageIndex = container.indexToPage(container.indexOfChild(parentLayout));
|
||||
final int pageCount = container.getChildCount();
|
||||
ViewGroup newParent = null;
|
||||
View child = null;
|
||||
// TODO(hyunyoungs): this matrix is not applicable on the last page.
|
||||
int[][] matrix = FocusLogic.createFullMatrix(countX, countY, true);
|
||||
// Initialize variables.
|
||||
final ShortcutAndWidgetContainer itemContainer = (ShortcutAndWidgetContainer) v.getParent();
|
||||
final CellLayout cellLayout = (CellLayout) itemContainer.getParent();
|
||||
final int countX = cellLayout.getCountX();
|
||||
final int countY = cellLayout.getCountY();
|
||||
|
||||
final int iconIndex = itemContainer.indexOfChild(v);
|
||||
final FolderPagedView pagedView = (FolderPagedView) cellLayout.getParent();
|
||||
|
||||
final int pageIndex = pagedView.indexOfChild(cellLayout);
|
||||
final int pageCount = pagedView.getPageCount();
|
||||
|
||||
int[][] matrix = FocusLogic.createSparseMatrix(cellLayout);
|
||||
// Process focus.
|
||||
int newIconIndex = FocusLogic.handleKeyEvent(keyCode, countX, countY, matrix,
|
||||
iconIndex, pageIndex, pageCount);
|
||||
@@ -126,60 +101,55 @@ public class FocusHelper {
|
||||
handleNoopKey(keyCode, v);
|
||||
return consume;
|
||||
}
|
||||
ShortcutAndWidgetContainer newParent = null;
|
||||
View child = null;
|
||||
|
||||
switch (newIconIndex) {
|
||||
case FocusLogic.PREVIOUS_PAGE_RIGHT_COLUMN:
|
||||
case FocusLogic.NEXT_PAGE_RIGHT_COLUMN:
|
||||
int newPageIndex = pageIndex - 1;
|
||||
if (newIconIndex == FocusLogic.NEXT_PAGE_RIGHT_COLUMN) {
|
||||
newPageIndex = pageIndex + 1;
|
||||
}
|
||||
newParent = getAppsCustomizePage(container, newPageIndex);
|
||||
case FocusLogic.PREVIOUS_PAGE_LEFT_COLUMN:
|
||||
newParent = getCellLayoutChildrenForIndex(pagedView, pageIndex - 1);
|
||||
if (newParent != null) {
|
||||
int row = FocusLogic.findRow(matrix, iconIndex);
|
||||
container.snapToPage(newPageIndex);
|
||||
// no need to create a new matrix.
|
||||
child = newParent.getChildAt(matrix[countX-1][row]);
|
||||
int row = ((CellLayout.LayoutParams) v.getLayoutParams()).cellY;
|
||||
pagedView.snapToPage(pageIndex - 1);
|
||||
child = newParent.getChildAt(
|
||||
((newIconIndex == FocusLogic.PREVIOUS_PAGE_LEFT_COLUMN)
|
||||
^ newParent.invertLayoutHorizontally()) ? 0 : countX - 1, row);
|
||||
}
|
||||
break;
|
||||
case FocusLogic.PREVIOUS_PAGE_FIRST_ITEM:
|
||||
newParent = getAppsCustomizePage(container, pageIndex - 1);
|
||||
newParent = getCellLayoutChildrenForIndex(pagedView, pageIndex - 1);
|
||||
if (newParent != null) {
|
||||
container.snapToPage(pageIndex - 1);
|
||||
child = newParent.getChildAt(0);
|
||||
pagedView.snapToPage(pageIndex - 1);
|
||||
child = newParent.getChildAt(0, 0);
|
||||
}
|
||||
break;
|
||||
case FocusLogic.PREVIOUS_PAGE_LAST_ITEM:
|
||||
newParent = getAppsCustomizePage(container, pageIndex - 1);
|
||||
newParent = getCellLayoutChildrenForIndex(pagedView, pageIndex - 1);
|
||||
if (newParent != null) {
|
||||
container.snapToPage(pageIndex - 1);
|
||||
child = newParent.getChildAt(newParent.getChildCount() - 1);
|
||||
pagedView.snapToPage(pageIndex - 1);
|
||||
child = newParent.getChildAt(countX - 1, countY - 1);
|
||||
}
|
||||
break;
|
||||
case FocusLogic.NEXT_PAGE_FIRST_ITEM:
|
||||
newParent = getAppsCustomizePage(container, pageIndex + 1);
|
||||
newParent = getCellLayoutChildrenForIndex(pagedView, pageIndex + 1);
|
||||
if (newParent != null) {
|
||||
container.snapToPage(pageIndex + 1);
|
||||
child = newParent.getChildAt(0);
|
||||
pagedView.snapToPage(pageIndex + 1);
|
||||
child = newParent.getChildAt(0, 0);
|
||||
}
|
||||
break;
|
||||
case FocusLogic.NEXT_PAGE_LEFT_COLUMN:
|
||||
case FocusLogic.PREVIOUS_PAGE_LEFT_COLUMN:
|
||||
newPageIndex = pageIndex + 1;
|
||||
if (newIconIndex == FocusLogic.PREVIOUS_PAGE_LEFT_COLUMN) {
|
||||
newPageIndex = pageIndex -1;
|
||||
}
|
||||
newParent = getAppsCustomizePage(container, newPageIndex);
|
||||
case FocusLogic.NEXT_PAGE_RIGHT_COLUMN:
|
||||
newParent = getCellLayoutChildrenForIndex(pagedView, pageIndex + 1);
|
||||
if (newParent != null) {
|
||||
container.snapToPage(newPageIndex);
|
||||
int row = FocusLogic.findRow(matrix, iconIndex);
|
||||
child = newParent.getChildAt(matrix[0][row]);
|
||||
pagedView.snapToPage(pageIndex + 1);
|
||||
child = FocusLogic.getAdjacentChildInNextPage(newParent, v, newIconIndex);
|
||||
}
|
||||
break;
|
||||
case FocusLogic.CURRENT_PAGE_FIRST_ITEM:
|
||||
child = container.getChildAt(0);
|
||||
child = cellLayout.getChildAt(0, 0);
|
||||
break;
|
||||
case FocusLogic.CURRENT_PAGE_LAST_ITEM:
|
||||
child = itemContainer.getChildAt(itemContainer.getChildCount() - 1);
|
||||
child = pagedView.getLastItem();
|
||||
break;
|
||||
default: // Go to some item on the current page.
|
||||
child = itemContainer.getChildAt(newIconIndex);
|
||||
@@ -194,7 +164,12 @@ public class FocusHelper {
|
||||
return consume;
|
||||
}
|
||||
|
||||
public void handleNoopKey(int keyCode, View v) { }
|
||||
public void handleNoopKey(int keyCode, View v) {
|
||||
if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
|
||||
mFolder.mFolderName.requestFocus();
|
||||
playSoundEffect(keyCode, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -226,7 +201,7 @@ public class FocusHelper {
|
||||
int pageCount = workspace.getChildCount();
|
||||
int countX = -1;
|
||||
int countY = -1;
|
||||
int iconIndex = findIndexOfView(hotseatParent, v);
|
||||
int iconIndex = hotseatParent.indexOfChild(v);
|
||||
int iconRank = ((CellLayout.LayoutParams) hotseatLayout.getShortcutsAndWidgets()
|
||||
.getChildAt(iconIndex).getLayoutParams()).cellX;
|
||||
|
||||
@@ -323,11 +298,12 @@ public class FocusHelper {
|
||||
final ViewGroup launcher = (ViewGroup) workspace.getParent();
|
||||
final ViewGroup tabs = (ViewGroup) launcher.findViewById(R.id.search_drop_target_bar);
|
||||
final Hotseat hotseat = (Hotseat) launcher.findViewById(R.id.hotseat);
|
||||
int pageIndex = workspace.indexOfChild(iconLayout);
|
||||
int pageCount = workspace.getChildCount();
|
||||
|
||||
final int iconIndex = parent.indexOfChild(v);
|
||||
final int pageIndex = workspace.indexOfChild(iconLayout);
|
||||
final int pageCount = workspace.getChildCount();
|
||||
int countX = iconLayout.getCountX();
|
||||
int countY = iconLayout.getCountY();
|
||||
final int iconIndex = findIndexOfView(parent, v);
|
||||
|
||||
CellLayout hotseatLayout = (CellLayout) hotseat.getChildAt(0);
|
||||
ShortcutAndWidgetContainer hotseatParent = hotseatLayout.getShortcutsAndWidgets();
|
||||
@@ -368,10 +344,11 @@ public class FocusHelper {
|
||||
if (newIconIndex == FocusLogic.NEXT_PAGE_RIGHT_COLUMN) {
|
||||
newPageIndex = pageIndex + 1;
|
||||
}
|
||||
int row = FocusLogic.findRow(matrix, iconIndex);
|
||||
int row = ((CellLayout.LayoutParams) v.getLayoutParams()).cellY;
|
||||
parent = getCellLayoutChildrenForIndex(workspace, newPageIndex);
|
||||
workspace.snapToPage(newPageIndex);
|
||||
if (parent != null) {
|
||||
workspace.snapToPage(newPageIndex);
|
||||
iconLayout = (CellLayout) parent.getParent();
|
||||
matrix = FocusLogic.createSparseMatrix(iconLayout,
|
||||
iconLayout.getCountX(), row);
|
||||
@@ -402,9 +379,10 @@ public class FocusHelper {
|
||||
newPageIndex = pageIndex - 1;
|
||||
}
|
||||
workspace.snapToPage(newPageIndex);
|
||||
row = FocusLogic.findRow(matrix, iconIndex);
|
||||
row = ((CellLayout.LayoutParams) v.getLayoutParams()).cellY;
|
||||
parent = getCellLayoutChildrenForIndex(workspace, newPageIndex);
|
||||
if (parent != null) {
|
||||
workspace.snapToPage(newPageIndex);
|
||||
iconLayout = (CellLayout) parent.getParent();
|
||||
matrix = FocusLogic.createSparseMatrix(iconLayout, -1, row);
|
||||
newIconIndex = FocusLogic.handleKeyEvent(keyCode, countX + 1, countY, matrix,
|
||||
@@ -439,18 +417,6 @@ public class FocusHelper {
|
||||
// Helper methods.
|
||||
//
|
||||
|
||||
/**
|
||||
* Returns the Viewgroup containing page contents for the page at the index specified.
|
||||
*/
|
||||
@Thunk static ViewGroup getAppsCustomizePage(ViewGroup container, int index) {
|
||||
ViewGroup page = (ViewGroup) ((PagedView) container).getPageAt(index);
|
||||
if (page instanceof CellLayout) {
|
||||
// There are two layers, a PagedViewCellLayout and PagedViewCellLayoutChildren
|
||||
page = ((CellLayout) page).getShortcutsAndWidgets();
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
/**
|
||||
* Private helper method to get the CellLayoutChildren given a CellLayout index.
|
||||
*/
|
||||
@@ -460,15 +426,6 @@ public class FocusHelper {
|
||||
return parent.getShortcutsAndWidgets();
|
||||
}
|
||||
|
||||
private static int findIndexOfView(ViewGroup parent, View v) {
|
||||
for (int i = 0; i < parent.getChildCount(); i++) {
|
||||
if (v != null && v.equals(parent.getChildAt(i))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to be used for playing sound effects.
|
||||
*/
|
||||
|
||||
@@ -177,7 +177,7 @@ public class ShortcutAndWidgetContainer extends ViewGroup {
|
||||
child.measure(childWidthMeasureSpec, childheightMeasureSpec);
|
||||
}
|
||||
|
||||
private boolean invertLayoutHorizontally() {
|
||||
public boolean invertLayoutHorizontally() {
|
||||
return mInvertIfRtl && isLayoutRtl();
|
||||
}
|
||||
|
||||
|
||||
@@ -18,11 +18,15 @@ package com.android.launcher3.util;
|
||||
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.android.launcher3.CellLayout;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.ShortcutAndWidgetContainer;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Calculates the next item that a {@link KeyEvent} should change the focus to.
|
||||
@@ -69,14 +73,11 @@ public class FocusLogic {
|
||||
* Returns true only if this utility class handles the key code.
|
||||
*/
|
||||
public static boolean shouldConsume(int keyCode) {
|
||||
if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT ||
|
||||
return (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_DEL || keyCode == KeyEvent.KEYCODE_FORWARD_DEL) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
keyCode == KeyEvent.KEYCODE_DEL || keyCode == KeyEvent.KEYCODE_FORWARD_DEL);
|
||||
}
|
||||
|
||||
public static int handleKeyEvent(int keyCode, int cntX, int cntY, int [][] map,
|
||||
@@ -138,33 +139,17 @@ public class FocusLogic {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a matrix of size (m x n) that has been initialized with incremental index starting
|
||||
* with 0 or a matrix where all the values are initialized to {@link #EMPTY}.
|
||||
* Returns a matrix of size (m x n) that has been initialized with {@link #EMPTY}.
|
||||
*
|
||||
* @param m number of columns in the matrix
|
||||
* @param n number of rows in the matrix
|
||||
* @param incrementOrder {@code true} if the matrix contents should increment in reading
|
||||
* order with 0 indexing. {@code false} if each cell should be
|
||||
* initialized to {@link #EMPTY};
|
||||
*/
|
||||
// TODO: get rid of dynamic matrix creation.
|
||||
public static int[][] createFullMatrix(int m, int n, boolean incrementOrder) {
|
||||
DeviceProfile profile = LauncherAppState.getInstance().getDynamicGrid()
|
||||
.getDeviceProfile();
|
||||
private static int[][] createFullMatrix(int m, int n) {
|
||||
int[][] matrix = new int [m][n];
|
||||
|
||||
for (int i=0; i < m;i++) {
|
||||
for (int j=0; j < n; j++) {
|
||||
if (incrementOrder) {
|
||||
if (!profile.isLayoutRtl) {
|
||||
matrix[i][j] = j * m + i;
|
||||
} else {
|
||||
matrix[i][j] = j * m + m - i -1;
|
||||
}
|
||||
} else {
|
||||
matrix[i][j] = EMPTY;
|
||||
}
|
||||
}
|
||||
Arrays.fill(matrix[i], EMPTY);
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
@@ -175,17 +160,18 @@ public class FocusLogic {
|
||||
*/
|
||||
// TODO: get rid of the dynamic matrix creation
|
||||
public static int[][] createSparseMatrix(CellLayout layout) {
|
||||
ViewGroup parent = layout.getShortcutsAndWidgets();
|
||||
ShortcutAndWidgetContainer parent = layout.getShortcutsAndWidgets();
|
||||
final int m = layout.getCountX();
|
||||
final int n = layout.getCountY();
|
||||
final boolean invert = parent.invertLayoutHorizontally();
|
||||
|
||||
int[][] matrix = createFullMatrix(m, n, false /* initialize to #EMPTY */);
|
||||
int[][] matrix = createFullMatrix(m, n);
|
||||
|
||||
// Iterate thru the children.
|
||||
for (int i = 0; i < parent.getChildCount(); i++ ) {
|
||||
int cx = ((CellLayout.LayoutParams) parent.getChildAt(i).getLayoutParams()).cellX;
|
||||
int cy = ((CellLayout.LayoutParams) parent.getChildAt(i).getLayoutParams()).cellY;
|
||||
matrix[cx][cy] = i;
|
||||
matrix[invert ? (m - cx - 1) : cx][cy] = i;
|
||||
}
|
||||
if (DEBUG) {
|
||||
printMatrix(matrix);
|
||||
@@ -213,7 +199,7 @@ public class FocusLogic {
|
||||
m = iconLayout.getCountX() + hotseatLayout.getCountX();
|
||||
n = iconLayout.getCountY();
|
||||
}
|
||||
int[][] matrix = createFullMatrix(m, n, false /* set all cell to empty */);
|
||||
int[][] matrix = createFullMatrix(m, n);
|
||||
|
||||
// Iterate thru the children of the top parent.
|
||||
for (int i = 0; i < iconParent.getChildCount(); i++) {
|
||||
@@ -267,8 +253,7 @@ public class FocusLogic {
|
||||
|
||||
ViewGroup iconParent = iconLayout.getShortcutsAndWidgets();
|
||||
|
||||
int[][] matrix = createFullMatrix(iconLayout.getCountX() + 1, iconLayout.getCountY(),
|
||||
false /* set all cell to empty */);
|
||||
int[][] matrix = createFullMatrix(iconLayout.getCountX() + 1, iconLayout.getCountY());
|
||||
|
||||
// Iterate thru the children of the top parent.
|
||||
for (int i = 0; i < iconParent.getChildCount(); i++) {
|
||||
@@ -499,22 +484,25 @@ public class FocusLogic {
|
||||
}
|
||||
|
||||
/**
|
||||
* Figure out the location of the icon.
|
||||
*
|
||||
* @param edgeColumn the column of the new icon. either {@link #NEXT_PAGE_LEFT_COLUMN} or
|
||||
* {@link #NEXT_PAGE_RIGHT_COLUMN}
|
||||
* @return the view adjacent to {@param oldView} in the {@param nextPage}.
|
||||
*/
|
||||
//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;
|
||||
public static View getAdjacentChildInNextPage(
|
||||
ShortcutAndWidgetContainer nextPage, View oldView, int edgeColumn) {
|
||||
final int newRow = ((CellLayout.LayoutParams) oldView.getLayoutParams()).cellY;
|
||||
|
||||
for (int i = 0; i < cntX; i++) {
|
||||
for (int j = 0; j < cntY; j++) {
|
||||
if (matrix[i][j] == iconIndex) {
|
||||
return j;
|
||||
int column = (edgeColumn == NEXT_PAGE_LEFT_COLUMN) ^ nextPage.invertLayoutHorizontally()
|
||||
? 0 : (((CellLayout) nextPage.getParent()).getCountX() - 1);
|
||||
|
||||
for (; column >= 0; column--) {
|
||||
for (int row = newRow; row >= 0; row--) {
|
||||
View newView = nextPage.getChildAt(column, row);
|
||||
if (newView != null) {
|
||||
return newView;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user