Add arrow key navigation support to Grid-based Recents.
Test: Checked that arrow key navigation works in Recents on local sw600dp devices. Also checked that Recents works properly on phones. Bug: 32101881 Change-Id: I8ece3fc4c9ae82916efcbbde72d40805e43cc70d
This commit is contained in:
@@ -74,6 +74,8 @@ import com.android.systemui.recents.events.ui.UserInteractionEvent;
|
||||
import com.android.systemui.recents.events.ui.focus.DismissFocusedTaskViewEvent;
|
||||
import com.android.systemui.recents.events.ui.focus.FocusNextTaskViewEvent;
|
||||
import com.android.systemui.recents.events.ui.focus.FocusPreviousTaskViewEvent;
|
||||
import com.android.systemui.recents.events.ui.focus.NavigateTaskViewEvent;
|
||||
import com.android.systemui.recents.events.ui.focus.NavigateTaskViewEvent.Direction;
|
||||
import com.android.systemui.recents.misc.DozeTrigger;
|
||||
import com.android.systemui.recents.misc.SystemServicesProxy;
|
||||
import com.android.systemui.recents.misc.Utilities;
|
||||
@@ -590,13 +592,12 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case KeyEvent.KEYCODE_DPAD_UP: {
|
||||
EventBus.getDefault().send(
|
||||
new FocusNextTaskViewEvent(0 /* timerIndicatorDuration */));
|
||||
return true;
|
||||
}
|
||||
case KeyEvent.KEYCODE_DPAD_DOWN: {
|
||||
EventBus.getDefault().send(new FocusPreviousTaskViewEvent());
|
||||
case KeyEvent.KEYCODE_DPAD_UP:
|
||||
case KeyEvent.KEYCODE_DPAD_DOWN:
|
||||
case KeyEvent.KEYCODE_DPAD_LEFT:
|
||||
case KeyEvent.KEYCODE_DPAD_RIGHT: {
|
||||
final Direction direction = NavigateTaskViewEvent.getDirectionFromKeyCode(keyCode);
|
||||
EventBus.getDefault().send(new NavigateTaskViewEvent(direction));
|
||||
return true;
|
||||
}
|
||||
case KeyEvent.KEYCODE_DEL:
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.systemui.recents.events.ui.focus;
|
||||
|
||||
import android.view.KeyEvent;
|
||||
import com.android.systemui.recents.events.EventBus;
|
||||
|
||||
/**
|
||||
* Navigates the task view by arrow keys.
|
||||
*/
|
||||
public class NavigateTaskViewEvent extends EventBus.Event {
|
||||
public enum Direction {
|
||||
UNDEFINED, UP, DOWN, LEFT, RIGHT;
|
||||
}
|
||||
|
||||
public Direction direction;
|
||||
public NavigateTaskViewEvent(Direction direction) {
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
public static Direction getDirectionFromKeyCode(int keyCode) {
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_DPAD_UP:
|
||||
return Direction.UP;
|
||||
case KeyEvent.KEYCODE_DPAD_DOWN:
|
||||
return Direction.DOWN;
|
||||
case KeyEvent.KEYCODE_DPAD_LEFT:
|
||||
return Direction.LEFT;
|
||||
case KeyEvent.KEYCODE_DPAD_RIGHT:
|
||||
return Direction.RIGHT;
|
||||
default:
|
||||
return Direction.UNDEFINED;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,6 +87,7 @@ import com.android.systemui.recents.events.ui.dragndrop.DragStartInitializeDropT
|
||||
import com.android.systemui.recents.events.ui.focus.DismissFocusedTaskViewEvent;
|
||||
import com.android.systemui.recents.events.ui.focus.FocusNextTaskViewEvent;
|
||||
import com.android.systemui.recents.events.ui.focus.FocusPreviousTaskViewEvent;
|
||||
import com.android.systemui.recents.events.ui.focus.NavigateTaskViewEvent;
|
||||
import com.android.systemui.recents.misc.DozeTrigger;
|
||||
import com.android.systemui.recents.misc.SystemServicesProxy;
|
||||
import com.android.systemui.recents.misc.Utilities;
|
||||
@@ -1869,6 +1870,26 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
setRelativeFocusedTask(false, false /* stackTasksOnly */, true /* animated */);
|
||||
}
|
||||
|
||||
public final void onBusEvent(NavigateTaskViewEvent event) {
|
||||
if (useGridLayout()) {
|
||||
final int taskCount = mStack.getTaskCount();
|
||||
final int currentIndex = mStack.indexOfStackTask(getFocusedTask());
|
||||
final int nextIndex = mLayoutAlgorithm.mTaskGridLayoutAlgorithm.navigateFocus(taskCount,
|
||||
currentIndex, event.direction);
|
||||
setFocusedTask(nextIndex, false, true);
|
||||
} else {
|
||||
switch (event.direction) {
|
||||
case UP:
|
||||
EventBus.getDefault().send(new FocusPreviousTaskViewEvent());
|
||||
break;
|
||||
case DOWN:
|
||||
EventBus.getDefault().send(
|
||||
new FocusNextTaskViewEvent(0 /* timerIndicatorDuration */));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final void onBusEvent(UserInteractionEvent event) {
|
||||
// Poke the doze trigger on user interaction
|
||||
mUIDozeTrigger.poke();
|
||||
|
||||
@@ -23,6 +23,8 @@ import android.graphics.Rect;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.recents.events.ui.focus.NavigateTaskViewEvent;
|
||||
import com.android.systemui.recents.events.ui.focus.NavigateTaskViewEvent.Direction;
|
||||
import com.android.systemui.recents.misc.Utilities;
|
||||
import com.android.systemui.recents.views.TaskStackLayoutAlgorithm;
|
||||
import com.android.systemui.recents.views.TaskViewTransform;
|
||||
@@ -63,6 +65,8 @@ public class TaskGridLayoutAlgorithm {
|
||||
Rect size;
|
||||
int[] xOffsets;
|
||||
int[] yOffsets;
|
||||
int tasksPerLine;
|
||||
int lines;
|
||||
|
||||
TaskGridRectInfo(int taskCount) {
|
||||
size = new Rect();
|
||||
@@ -71,10 +75,10 @@ public class TaskGridLayoutAlgorithm {
|
||||
|
||||
int layoutTaskCount = Math.min(MAX_LAYOUT_TASK_COUNT, taskCount);
|
||||
|
||||
int tasksPerLine = layoutTaskCount < 2 ? 1 : (
|
||||
tasksPerLine = layoutTaskCount < 2 ? 1 : (
|
||||
layoutTaskCount < 5 ? 2 : (
|
||||
layoutTaskCount < 7 ? 3 : 4));
|
||||
int lines = layoutTaskCount < 3 ? 1 : 2;
|
||||
lines = layoutTaskCount < 3 ? 1 : 2;
|
||||
|
||||
// A couple of special cases.
|
||||
boolean landscapeWindow = mWindowRect.width() > mWindowRect.height();
|
||||
@@ -200,6 +204,48 @@ public class TaskGridLayoutAlgorithm {
|
||||
return transformOut;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the proper task index to focus for arrow key navigation.
|
||||
* @param taskCount The amount of tasks.
|
||||
* @param currentFocusedIndex The index of the currently focused task.
|
||||
* @param direction The direction we're navigating.
|
||||
* @return The index of the task that should get the focus.
|
||||
*/
|
||||
public int navigateFocus(int taskCount, int currentFocusedIndex, Direction direction) {
|
||||
if (taskCount < 1 || taskCount > MAX_LAYOUT_TASK_COUNT) {
|
||||
return -1;
|
||||
}
|
||||
if (currentFocusedIndex == -1) {
|
||||
return 0;
|
||||
}
|
||||
int newIndex = currentFocusedIndex;
|
||||
final TaskGridRectInfo gridInfo = mTaskGridRectInfoList[taskCount - 1];
|
||||
final int currentLine = (taskCount - 1 - currentFocusedIndex) / gridInfo.tasksPerLine;
|
||||
switch (direction) {
|
||||
case UP:
|
||||
newIndex += gridInfo.tasksPerLine;
|
||||
newIndex = newIndex >= taskCount ? currentFocusedIndex : newIndex;
|
||||
break;
|
||||
case DOWN:
|
||||
newIndex -= gridInfo.tasksPerLine;
|
||||
newIndex = newIndex < 0 ? currentFocusedIndex : newIndex;
|
||||
break;
|
||||
case LEFT:
|
||||
newIndex++;
|
||||
final int leftMostIndex = (taskCount - 1) - currentLine * gridInfo.tasksPerLine;
|
||||
newIndex = newIndex > leftMostIndex ? currentFocusedIndex : newIndex;
|
||||
break;
|
||||
case RIGHT:
|
||||
newIndex--;
|
||||
int rightMostIndex =
|
||||
(taskCount - 1) - (currentLine + 1) * gridInfo.tasksPerLine + 1;
|
||||
rightMostIndex = rightMostIndex < 0 ? 0 : rightMostIndex;
|
||||
newIndex = newIndex < rightMostIndex ? currentFocusedIndex : newIndex;
|
||||
break;
|
||||
}
|
||||
return newIndex;
|
||||
}
|
||||
|
||||
public void initialize(Rect windowRect) {
|
||||
mWindowRect = windowRect;
|
||||
// Define paddings in terms of percentage of the total area.
|
||||
|
||||
Reference in New Issue
Block a user