/*
|
* Copyright (C) 2015 The Android Open Source Project
|
*
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
* you may not use this file except in compliance with the License.
|
* You may obtain a copy of the License at
|
*
|
* http://www.apache.org/licenses/LICENSE-2.0
|
*
|
* Unless required by applicable law or agreed to in writing, software
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* See the License for the specific language governing permissions and
|
* limitations under the License.
|
*/
|
|
package com.android.launcher3;
|
|
import android.util.Log;
|
import android.view.KeyEvent;
|
import android.view.SoundEffectConstants;
|
import android.view.View;
|
import android.view.ViewGroup;
|
|
import com.android.launcher3.config.FeatureFlags;
|
import com.android.launcher3.folder.Folder;
|
import com.android.launcher3.folder.FolderPagedView;
|
import com.android.launcher3.util.FocusLogic;
|
import com.android.launcher3.util.Thunk;
|
|
/**
|
* A keyboard listener we set on all the workspace icons.
|
*/
|
class IconKeyEventListener implements View.OnKeyListener {
|
@Override
|
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
return FocusHelper.handleIconKeyEvent(v, keyCode, event);
|
}
|
}
|
|
/**
|
* A keyboard listener we set on all the hotseat buttons.
|
*/
|
class HotseatIconKeyEventListener implements View.OnKeyListener {
|
@Override
|
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
return FocusHelper.handleHotseatButtonKeyEvent(v, keyCode, event);
|
}
|
}
|
|
/**
|
* A keyboard listener we set on full screen pages (e.g. custom content).
|
*/
|
class FullscreenKeyEventListener implements View.OnKeyListener {
|
@Override
|
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT
|
|| keyCode == KeyEvent.KEYCODE_PAGE_DOWN || keyCode == KeyEvent.KEYCODE_PAGE_UP) {
|
// Handle the key event just like a workspace icon would in these cases. In this case,
|
// it will basically act as if there is a single icon in the top left (so you could
|
// think of the fullscreen page as a focusable fullscreen widget).
|
return FocusHelper.handleIconKeyEvent(v, keyCode, event);
|
}
|
return false;
|
}
|
}
|
|
/**
|
* TODO: Reevaluate if this is still required
|
*/
|
public class FocusHelper {
|
|
private static final String TAG = "FocusHelper";
|
private static final boolean DEBUG = false;
|
|
/**
|
* Handles key events in paged folder.
|
*/
|
public static class PagedFolderKeyEventListener implements View.OnKeyListener {
|
|
private final Folder mFolder;
|
|
public PagedFolderKeyEventListener(Folder folder) {
|
mFolder = folder;
|
}
|
|
@Override
|
public boolean onKey(View v, int keyCode, KeyEvent e) {
|
boolean consume = FocusLogic.shouldConsume(keyCode);
|
if (e.getAction() == KeyEvent.ACTION_UP) {
|
return consume;
|
}
|
if (DEBUG) {
|
Log.v(TAG, String.format("Handle ALL Folders keyevent=[%s].",
|
KeyEvent.keyCodeToString(keyCode)));
|
}
|
|
if (!(v.getParent() instanceof ShortcutAndWidgetContainer)) {
|
if (FeatureFlags.IS_DOGFOOD_BUILD) {
|
throw new IllegalStateException("Parent of the focused item is not supported.");
|
} else {
|
return false;
|
}
|
}
|
|
// Initialize variables.
|
final ShortcutAndWidgetContainer itemContainer = (ShortcutAndWidgetContainer) v.getParent();
|
final CellLayout cellLayout = (CellLayout) itemContainer.getParent();
|
|
final int iconIndex = itemContainer.indexOfChild(v);
|
final FolderPagedView pagedView = (FolderPagedView) cellLayout.getParent();
|
|
final int pageIndex = pagedView.indexOfChild(cellLayout);
|
final int pageCount = pagedView.getPageCount();
|
final boolean isLayoutRtl = Utilities.isRtl(v.getResources());
|
|
int[][] matrix = FocusLogic.createSparseMatrix(cellLayout);
|
// Process focus.
|
int newIconIndex = FocusLogic.handleKeyEvent(keyCode, matrix, iconIndex, pageIndex,
|
pageCount, isLayoutRtl);
|
if (newIconIndex == FocusLogic.NOOP) {
|
handleNoopKey(keyCode, v);
|
return consume;
|
}
|
ShortcutAndWidgetContainer newParent = null;
|
View child = null;
|
|
switch (newIconIndex) {
|
case FocusLogic.PREVIOUS_PAGE_RIGHT_COLUMN:
|
case FocusLogic.PREVIOUS_PAGE_LEFT_COLUMN:
|
newParent = getCellLayoutChildrenForIndex(pagedView, pageIndex - 1);
|
if (newParent != null) {
|
int row = ((CellLayout.LayoutParams) v.getLayoutParams()).cellY;
|
pagedView.snapToPage(pageIndex - 1);
|
child = newParent.getChildAt(
|
((newIconIndex == FocusLogic.PREVIOUS_PAGE_LEFT_COLUMN)
|
^ newParent.invertLayoutHorizontally()) ? 0 : matrix.length - 1,
|
row);
|
}
|
break;
|
case FocusLogic.PREVIOUS_PAGE_FIRST_ITEM:
|
newParent = getCellLayoutChildrenForIndex(pagedView, pageIndex - 1);
|
if (newParent != null) {
|
pagedView.snapToPage(pageIndex - 1);
|
child = newParent.getChildAt(0, 0);
|
}
|
break;
|
case FocusLogic.PREVIOUS_PAGE_LAST_ITEM:
|
newParent = getCellLayoutChildrenForIndex(pagedView, pageIndex - 1);
|
if (newParent != null) {
|
pagedView.snapToPage(pageIndex - 1);
|
child = newParent.getChildAt(matrix.length - 1, matrix[0].length - 1);
|
}
|
break;
|
case FocusLogic.NEXT_PAGE_FIRST_ITEM:
|
newParent = getCellLayoutChildrenForIndex(pagedView, pageIndex + 1);
|
if (newParent != null) {
|
pagedView.snapToPage(pageIndex + 1);
|
child = newParent.getChildAt(0, 0);
|
}
|
break;
|
case FocusLogic.NEXT_PAGE_LEFT_COLUMN:
|
case FocusLogic.NEXT_PAGE_RIGHT_COLUMN:
|
newParent = getCellLayoutChildrenForIndex(pagedView, pageIndex + 1);
|
if (newParent != null) {
|
pagedView.snapToPage(pageIndex + 1);
|
child = FocusLogic.getAdjacentChildInNextFolderPage(
|
newParent, v, newIconIndex);
|
}
|
break;
|
case FocusLogic.CURRENT_PAGE_FIRST_ITEM:
|
child = cellLayout.getChildAt(0, 0);
|
break;
|
case FocusLogic.CURRENT_PAGE_LAST_ITEM:
|
child = pagedView.getLastItem();
|
break;
|
default: // Go to some item on the current page.
|
child = itemContainer.getChildAt(newIconIndex);
|
break;
|
}
|
if (child != null) {
|
child.requestFocus();
|
playSoundEffect(keyCode, v);
|
} else {
|
handleNoopKey(keyCode, v);
|
}
|
return consume;
|
}
|
|
public void handleNoopKey(int keyCode, View v) {
|
if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
|
mFolder.mFolderName.requestFocus();
|
playSoundEffect(keyCode, v);
|
}
|
}
|
}
|
|
/**
|
* Handles key events in the workspace hotseat (bottom of the screen).
|
* <p>Currently we don't special case for the phone UI in different orientations, even though
|
* the hotseat is on the side in landscape mode. This is to ensure that accessibility
|
* consistency is maintained across rotations.
|
*/
|
static boolean handleHotseatButtonKeyEvent(View v, int keyCode, KeyEvent e) {
|
boolean consume = FocusLogic.shouldConsume(keyCode);
|
if (e.getAction() == KeyEvent.ACTION_UP || !consume) {
|
return consume;
|
}
|
|
final Launcher launcher = Launcher.getLauncher(v.getContext());
|
final DeviceProfile profile = launcher.getDeviceProfile();
|
|
if (DEBUG) {
|
Log.v(TAG, String.format(
|
"Handle HOTSEAT BUTTONS keyevent=[%s] on hotseat buttons, isVertical=%s",
|
KeyEvent.keyCodeToString(keyCode), profile.isVerticalBarLayout()));
|
}
|
|
// Initialize the variables.
|
final Workspace workspace = (Workspace) v.getRootView().findViewById(R.id.workspace);
|
final ShortcutAndWidgetContainer hotseatParent = (ShortcutAndWidgetContainer) v.getParent();
|
final CellLayout hotseatLayout = (CellLayout) hotseatParent.getParent();
|
|
final ItemInfo itemInfo = (ItemInfo) v.getTag();
|
int pageIndex = workspace.getNextPage();
|
int pageCount = workspace.getChildCount();
|
int iconIndex = hotseatParent.indexOfChild(v);
|
int iconRank = ((CellLayout.LayoutParams) hotseatLayout.getShortcutsAndWidgets()
|
.getChildAt(iconIndex).getLayoutParams()).cellX;
|
|
final CellLayout iconLayout = (CellLayout) workspace.getChildAt(pageIndex);
|
if (iconLayout == null) {
|
// This check is to guard against cases where key strokes rushes in when workspace
|
// child creation/deletion is still in flux. (e.g., during drop or fling
|
// animation.)
|
return consume;
|
}
|
final ViewGroup iconParent = iconLayout.getShortcutsAndWidgets();
|
|
ViewGroup parent = null;
|
int[][] matrix = null;
|
|
if (keyCode == KeyEvent.KEYCODE_DPAD_UP &&
|
!profile.isVerticalBarLayout()) {
|
matrix = FocusLogic.createSparseMatrixWithHotseat(iconLayout, hotseatLayout, profile);
|
iconIndex += iconParent.getChildCount();
|
parent = iconParent;
|
} else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT &&
|
profile.isVerticalBarLayout()) {
|
matrix = FocusLogic.createSparseMatrixWithHotseat(iconLayout, hotseatLayout, profile);
|
iconIndex += iconParent.getChildCount();
|
parent = iconParent;
|
} else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT &&
|
profile.isVerticalBarLayout()) {
|
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;
|
}
|
|
// Process the focus.
|
int newIconIndex = FocusLogic.handleKeyEvent(keyCode, matrix, iconIndex, pageIndex,
|
pageCount, Utilities.isRtl(v.getResources()));
|
|
View newIcon = null;
|
switch (newIconIndex) {
|
case 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);
|
break;
|
case FocusLogic.PREVIOUS_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);
|
break;
|
case FocusLogic.PREVIOUS_PAGE_LAST_ITEM:
|
parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
|
newIcon = parent.getChildAt(parent.getChildCount() - 1);
|
// TODO(hyunyoungs): handle cases where the child is not an icon but
|
// a folder or a widget.
|
workspace.snapToPage(pageIndex - 1);
|
break;
|
case FocusLogic.PREVIOUS_PAGE_LEFT_COLUMN:
|
case FocusLogic.PREVIOUS_PAGE_RIGHT_COLUMN:
|
// Go to the previous page but keep the focus on the same hotseat icon.
|
workspace.snapToPage(pageIndex - 1);
|
break;
|
case FocusLogic.NEXT_PAGE_LEFT_COLUMN:
|
case FocusLogic.NEXT_PAGE_RIGHT_COLUMN:
|
// Go to the next page but keep the focus on the same hotseat icon.
|
workspace.snapToPage(pageIndex + 1);
|
break;
|
}
|
if (parent == iconParent && newIconIndex >= iconParent.getChildCount()) {
|
newIconIndex -= iconParent.getChildCount();
|
}
|
if (parent != null) {
|
if (newIcon == null && newIconIndex >= 0) {
|
newIcon = parent.getChildAt(newIconIndex);
|
}
|
if (newIcon != null) {
|
newIcon.requestFocus();
|
playSoundEffect(keyCode, v);
|
}
|
}
|
return consume;
|
}
|
|
/**
|
* Handles key events in a workspace containing icons.
|
*/
|
static boolean handleIconKeyEvent(View v, int keyCode, KeyEvent e) {
|
boolean consume = FocusLogic.shouldConsume(keyCode);
|
if (e.getAction() == KeyEvent.ACTION_UP || !consume) {
|
return consume;
|
}
|
|
Launcher launcher = Launcher.getLauncher(v.getContext());
|
DeviceProfile profile = launcher.getDeviceProfile();
|
|
if (DEBUG) {
|
Log.v(TAG, String.format("Handle WORKSPACE ICONS keyevent=[%s] isVerticalBar=%s",
|
KeyEvent.keyCodeToString(keyCode), profile.isVerticalBarLayout()));
|
}
|
|
// Initialize the variables.
|
ShortcutAndWidgetContainer parent = (ShortcutAndWidgetContainer) v.getParent();
|
CellLayout iconLayout = (CellLayout) parent.getParent();
|
final Workspace workspace = (Workspace) iconLayout.getParent();
|
final ViewGroup dragLayer = (ViewGroup) workspace.getParent();
|
final ViewGroup tabs = (ViewGroup) dragLayer.findViewById(R.id.drop_target_bar);
|
final Hotseat hotseat = (Hotseat) dragLayer.findViewById(R.id.hotseat);
|
|
final ItemInfo itemInfo = (ItemInfo) v.getTag();
|
final int iconIndex = parent.indexOfChild(v);
|
final int pageIndex = workspace.indexOfChild(iconLayout);
|
final int pageCount = workspace.getChildCount();
|
|
CellLayout hotseatLayout = (CellLayout) hotseat.getChildAt(0);
|
ShortcutAndWidgetContainer hotseatParent = hotseatLayout.getShortcutsAndWidgets();
|
int[][] matrix;
|
|
// 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 && !profile.isVerticalBarLayout()) {
|
matrix = FocusLogic.createSparseMatrixWithHotseat(iconLayout, hotseatLayout, profile);
|
} else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT &&
|
profile.isVerticalBarLayout()) {
|
matrix = FocusLogic.createSparseMatrixWithHotseat(iconLayout, hotseatLayout, profile);
|
} else {
|
matrix = FocusLogic.createSparseMatrix(iconLayout);
|
}
|
|
// Process the focus.
|
int newIconIndex = FocusLogic.handleKeyEvent(keyCode, 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) {
|
newIcon = tabs;
|
}
|
break;
|
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;
|
}
|
int row = ((CellLayout.LayoutParams) v.getLayoutParams()).cellY;
|
parent = getCellLayoutChildrenForIndex(workspace, newPageIndex);
|
if (parent != null) {
|
iconLayout = (CellLayout) parent.getParent();
|
matrix = FocusLogic.createSparseMatrixWithPivotColumn(iconLayout,
|
iconLayout.getCountX(), row);
|
newIconIndex = FocusLogic.handleKeyEvent(keyCode, matrix, FocusLogic.PIVOT,
|
newPageIndex, pageCount, Utilities.isRtl(v.getResources()));
|
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:
|
workspaceLayout = (CellLayout) workspace.getChildAt(pageIndex - 1);
|
newIcon = getFirstFocusableIconInReadingOrder(workspaceLayout, isRtl);
|
if (newIcon == null) {
|
// Check the hotseat if no focusable item was found on the workspace.
|
newIcon = getFirstFocusableIconInReadingOrder(hotseatLayout, isRtl);
|
workspace.snapToPage(pageIndex - 1);
|
}
|
break;
|
case FocusLogic.PREVIOUS_PAGE_LAST_ITEM:
|
newIcon = handlePreviousPageLastItem(workspace, hotseatLayout, pageIndex, isRtl);
|
break;
|
case FocusLogic.NEXT_PAGE_FIRST_ITEM:
|
newIcon = handleNextPageFirstItem(workspace, hotseatLayout, pageIndex, isRtl);
|
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;
|
}
|
row = ((CellLayout.LayoutParams) v.getLayoutParams()).cellY;
|
parent = getCellLayoutChildrenForIndex(workspace, newPageIndex);
|
if (parent != null) {
|
iconLayout = (CellLayout) parent.getParent();
|
matrix = FocusLogic.createSparseMatrixWithPivotColumn(iconLayout, -1, row);
|
newIconIndex = FocusLogic.handleKeyEvent(keyCode, matrix, FocusLogic.PIVOT,
|
newPageIndex, pageCount, Utilities.isRtl(v.getResources()));
|
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 = getFirstFocusableIconInReadingOrder(workspaceLayout, isRtl);
|
if (newIcon == null) {
|
// Check the hotseat if no focusable item was found on the workspace.
|
newIcon = getFirstFocusableIconInReadingOrder(hotseatLayout, isRtl);
|
}
|
break;
|
case FocusLogic.CURRENT_PAGE_LAST_ITEM:
|
newIcon = getFirstFocusableIconInReverseReadingOrder(workspaceLayout, isRtl);
|
if (newIcon == null) {
|
// Check the hotseat if no focusable item was found on the workspace.
|
newIcon = getFirstFocusableIconInReverseReadingOrder(hotseatLayout, isRtl);
|
}
|
break;
|
default:
|
// current page, some item.
|
if (0 <= newIconIndex && newIconIndex < parent.getChildCount()) {
|
newIcon = parent.getChildAt(newIconIndex);
|
} else if (parent.getChildCount() <= newIconIndex &&
|
newIconIndex < parent.getChildCount() + hotseatParent.getChildCount()) {
|
newIcon = hotseatParent.getChildAt(newIconIndex - parent.getChildCount());
|
}
|
break;
|
}
|
if (newIcon != null) {
|
newIcon.requestFocus();
|
playSoundEffect(keyCode, v);
|
}
|
return consume;
|
}
|
|
//
|
// Helper methods.
|
//
|
|
/**
|
* Private helper method to get the CellLayoutChildren given a CellLayout index.
|
*/
|
@Thunk static ShortcutAndWidgetContainer getCellLayoutChildrenForIndex(
|
ViewGroup container, int i) {
|
CellLayout parent = (CellLayout) container.getChildAt(i);
|
return parent.getShortcutsAndWidgets();
|
}
|
|
/**
|
* Helper method to be used for playing sound effects.
|
*/
|
@Thunk static void playSoundEffect(int keyCode, View v) {
|
switch (keyCode) {
|
case KeyEvent.KEYCODE_DPAD_LEFT:
|
v.playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT);
|
break;
|
case KeyEvent.KEYCODE_DPAD_RIGHT:
|
v.playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT);
|
break;
|
case KeyEvent.KEYCODE_DPAD_DOWN:
|
case KeyEvent.KEYCODE_PAGE_DOWN:
|
case KeyEvent.KEYCODE_MOVE_END:
|
v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN);
|
break;
|
case KeyEvent.KEYCODE_DPAD_UP:
|
case KeyEvent.KEYCODE_PAGE_UP:
|
case KeyEvent.KEYCODE_MOVE_HOME:
|
v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
|
break;
|
default:
|
break;
|
}
|
}
|
|
private static View handlePreviousPageLastItem(Workspace workspace, CellLayout hotseatLayout,
|
int pageIndex, boolean isRtl) {
|
if (pageIndex - 1 < 0) {
|
return null;
|
}
|
CellLayout workspaceLayout = (CellLayout) workspace.getChildAt(pageIndex - 1);
|
View newIcon = getFirstFocusableIconInReverseReadingOrder(workspaceLayout, isRtl);
|
if (newIcon == null) {
|
// Check the hotseat if no focusable item was found on the workspace.
|
newIcon = getFirstFocusableIconInReverseReadingOrder(hotseatLayout,isRtl);
|
workspace.snapToPage(pageIndex - 1);
|
}
|
return newIcon;
|
}
|
|
private static View handleNextPageFirstItem(Workspace workspace, CellLayout hotseatLayout,
|
int pageIndex, boolean isRtl) {
|
if (pageIndex + 1 >= workspace.getPageCount()) {
|
return null;
|
}
|
CellLayout workspaceLayout = (CellLayout) workspace.getChildAt(pageIndex + 1);
|
View newIcon = getFirstFocusableIconInReadingOrder(workspaceLayout, isRtl);
|
if (newIcon == null) {
|
// Check the hotseat if no focusable item was found on the workspace.
|
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;
|
}
|
}
|