Android 7.1 + RK3288
系统支持遥控操作, 但是, 在主界面时, 无法打开所有应用列表.
在主界面, 不管上下左右如何操作, 都无法打开应用列表.
diff --git a/packages/apps/Launcher3/src_config/com/android/launcher3/config/FeatureFlags.java b/packages/apps/Launcher3/src_config/com/android/launcher3/config/FeatureFlags.java
index 8ee5497..ed35fda 100644
--- a/packages/apps/Launcher3/src_config/com/android/launcher3/config/FeatureFlags.java
+++ b/packages/apps/Launcher3/src_config/com/android/launcher3/config/FeatureFlags.java
@@ -34,7 +34,7 @@ public final class FeatureFlags {
// Feature flag to enable moving the QSB on the 0th screen of the workspace.
public static final boolean QSB_ON_FIRST_SCREEN = true;
// When enabled the all-apps icon is not added to the hotseat.
- public static final boolean NO_ALL_APPS_ICON = true;
+ public static final boolean NO_ALL_APPS_ICON = false;
// When enabled fling down gesture on the first workspace triggers search.
public static final boolean PULLDOWN_SEARCH = false;
// When enabled the status bar may show dark icons based on the top of the wallpaper.
diff --git a/packages/apps/Launcher3/res/layout/page_indicator.xml b/packages/apps/Launcher3/res/layout/page_indicator.xml
index 2e1b57f..22ef0b4 100644
--- a/packages/apps/Launcher3/res/layout/page_indicator.xml
+++ b/packages/apps/Launcher3/res/layout/page_indicator.xml
@@ -23,5 +23,7 @@
android:layout_width="48dp"
android:layout_height="match_parent"
android:layout_gravity="center"
- android:scaleType="centerInside"/>
+ android:focusable="true"
+ android:scaleType="centerInside"
+ android:background="@drawable/bg_pill_focused"/>
diff --git a/packages/apps/Launcher3/src/com/android/launcher3/FocusHelper.java b/packages/apps/Launcher3/src/com/android/launcher3/FocusHelper.java
index 789c3f9..3071152 100644
--- a/packages/apps/Launcher3/src/com/android/launcher3/FocusHelper.java
+++ b/packages/apps/Launcher3/src/com/android/launcher3/FocusHelper.java
@@ -268,7 +268,6 @@ public class FocusHelper {
// 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:
@@ -329,6 +328,11 @@ public class FocusHelper {
playSoundEffect(keyCode, v);
}
}
+
+ //support focus all apps.
+ if(FocusLogic.NOOP == newIconIndex){
+ v.getRootView().findViewById(R.id.all_apps_handle).requestFocus();
+ }
return consume;
}
在Hotseat上, 按DPAD_DOWN, ^ 键可以获取焦点, 再输入 DPAD_CENTER, 即可打开应用列表
效果如图:
定义了按键处理监听, 供 Hotseat-Icon 使用
|-- packages/apps/Launcher3/src/com/android/launcher3/FocusHelper.java
/**
* 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;
}
}
/**
* Handles key events in the workspace hotseat (bottom of the screen).
* 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 if (isUninstallKeyChord(e)) {
matrix = FocusLogic.createSparseMatrix(iconLayout);
if (UninstallDropTarget.supportsDrop(launcher, itemInfo)) {
UninstallDropTarget.startUninstallActivity(launcher, itemInfo);
}
} else if (isDeleteKeyChord(e)) {
matrix = FocusLogic.createSparseMatrix(iconLayout);
launcher.removeItem(v, itemInfo, true /* deleteFromDb */);
} 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);
// If the page we are going to is fullscreen, have it take the focus from hotseat.
CellLayout prevPage = (CellLayout) workspace.getPageAt(pageIndex - 1);
boolean isPrevPageFullscreen = ((CellLayout.LayoutParams) prevPage
.getShortcutsAndWidgets().getChildAt(0).getLayoutParams()).isFullscreen;
if (isPrevPageFullscreen) {
workspace.getPageAt(pageIndex - 1).requestFocus();
}
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);
// If the page we are going to is fullscreen, have it take the focus from hotseat.
CellLayout nextPage = (CellLayout) workspace.getPageAt(pageIndex + 1);
boolean isNextPageFullscreen = ((CellLayout.LayoutParams) nextPage
.getShortcutsAndWidgets().getChildAt(0).getLayoutParams()).isFullscreen;
if (isNextPageFullscreen) {
workspace.getPageAt(pageIndex + 1).requestFocus();
}
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);
}
}
//当HOTSEAT中的ICON获取到焦点, 并触发了按键DOWN时, newIconIndex = -1.
//Support focuse all apps.
if(FocusLogic.NOOP == newIconIndex){
//让 ^ 键请求焦点
//当然, 也可以直接调用显示所有应用的函数显示应用列表
v.getRootView().findViewById(R.id.all_apps_handle).requestFocus();
}
return consume;
}
|-- packages/apps/Launcher3/src/com/android/launcher3/Workspace.java
void addInScreen(View child, long container, long screenId, int x, int y, int spanX, int spanY,
boolean insert, boolean computeXYFromRank) {
if (container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
if (getScreenWithId(screenId) == null) {
Log.e(TAG, "Skipping child, screenId " + screenId + " not found");
// DEBUGGING - Print out the stack trace to see where we are adding from
new Throwable().printStackTrace();
return;
}
}
if (screenId == EXTRA_EMPTY_SCREEN_ID) {
// This should never happen
throw new RuntimeException("Screen id should not be EXTRA_EMPTY_SCREEN_ID");
}
final CellLayout layout;
if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
layout = mLauncher.getHotseat().getLayout();
child.setOnKeyListener(new HotseatIconKeyEventListener());
// Hide folder title in the hotseat
if (child instanceof FolderIcon) {
((FolderIcon) child).setTextVisible(false);
}
if (computeXYFromRank) {
x = mLauncher.getHotseat().getCellXFromOrder((int) screenId);
y = mLauncher.getHotseat().getCellYFromOrder((int) screenId);
} else {
screenId = mLauncher.getHotseat().getOrderInHotseat(x, y);
}
} else {
// Show folder title if not in the hotseat
if (child instanceof FolderIcon) {
((FolderIcon) child).setTextVisible(true);
}
layout = getScreenWithId(screenId);
child.setOnKeyListener(new IconKeyEventListener());
}
...
}
|-- packages/apps/Launcher3/src/com/android/launcher3/Hotseat.java
void resetLayout() {
mContent.removeAllViewsInLayout();
if (!FeatureFlags.NO_ALL_APPS_ICON) {
// Add the Apps button
Context context = getContext();
int allAppsButtonRank = mLauncher.getDeviceProfile().inv.getAllAppsButtonRank();
LayoutInflater inflater = LayoutInflater.from(context);
TextView allAppsButton = (TextView)
inflater.inflate(R.layout.all_apps_button, mContent, false);
Drawable d = context.getResources().getDrawable(R.drawable.all_apps_button_icon);
mLauncher.resizeIconDrawable(d);
int scaleDownPx = getResources().getDimensionPixelSize(R.dimen.all_apps_button_scale_down);
Rect bounds = d.getBounds();
d.setBounds(bounds.left, bounds.top + scaleDownPx / 2, bounds.right - scaleDownPx,
bounds.bottom - scaleDownPx / 2);
allAppsButton.setCompoundDrawables(null, d, null, null);
allAppsButton.setContentDescription(context.getString(R.string.all_apps_button_label));
allAppsButton.setOnKeyListener(new HotseatIconKeyEventListener());
if (mLauncher != null) {
mLauncher.setAllAppsButton(allAppsButton);
allAppsButton.setOnTouchListener(mLauncher.getHapticFeedbackTouchListener());
allAppsButton.setOnClickListener(mLauncher);
allAppsButton.setOnLongClickListener(mLauncher);
allAppsButton.setOnFocusChangeListener(mLauncher.mFocusHandler);
}
// Note: We do this to ensure that the hotseat is always laid out in the orientation of
// the hotseat in order regardless of which orientation they were added
int x = getCellXFromOrder(allAppsButtonRank);
int y = getCellYFromOrder(allAppsButtonRank);
CellLayout.LayoutParams lp = new CellLayout.LayoutParams(x, y, 1, 1);
lp.canReorder = false;
mContent.addViewToCellLayout(allAppsButton, -1, allAppsButton.getId(), lp, true);
}
}