平台

Android 7.1 + RK3288

问题

系统支持遥控操作, 但是, 在主界面时, 无法打开所有应用列表.在主界面, 不管上下左右如何操作, 都无法打开应用列表.

Android 7.1 Launcher3 支持按键操作显示所有应用_第1张图片
Android 7.1 Launcher3 支持按键操作显示所有应用_第2张图片

解决方案

与旧版相似, 显示所有应用图标

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.javaindex 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.

效果图如下:
Android 7.1 Launcher3 支持按键操作显示所有应用_第3张图片

在现有的UI中, 增加 ^ 键的焦点使能

diff --git a/packages/apps/Launcher3/res/layout/page_indicator.xml b/packages/apps/Launcher3/res/layout/page_indicator.xmlindex 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.javaindex 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, 即可打开应用列表
效果如图:
Android 7.1 Launcher3 支持按键操作显示所有应用_第4张图片

处理焦点的相关代码

定义了按键处理监听, 供 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);        }    }

更多相关文章

  1. Android View如何获取焦点
  2. Android系统移植(二)-按键移植
  3. Android之怎么操作文件(读写以及保存到sdcard)
  4. 在Visual Studio 2013/2015上使用C#开发Android/IOS安装包和操作
  5. Android使用SQLiteDatabase操作SQLite数据库

随机推荐

  1. android permission中英文大全
  2. android View的点击事件分发机制的简单认
  3. Android(安卓)UI之五种基本布局详解
  4. android 短信的接收和发送处理
  5. Android中代替枚举的@IntDef用法
  6. android中子线程更新UI的方式浅析
  7. Android(安卓)WebView 加载本地SD卡的htm
  8. Android(安卓)逆向
  9. Android中的ClassLoader
  10. android系统中的多线程(二): 关于在work