From 5dd045bec67ca12a3de4b4adc88a92a0166c0f50 Mon Sep 17 00:00:00 2001 From: Hyunyoung Song Date: Tue, 4 Aug 2020 22:22:49 -0700 Subject: [PATCH] Handle IME selection focus for ENABLE_DEVICE_SEARCH Bug: 162861289 Change-Id: I15e4eae09be2aa9f89a5157fd74c95e91e64bc53 --- .../appprediction/AppsDividerView.java | 5 +++ .../appprediction/PredictionRowView.java | 8 +++- res/values/colors.xml | 3 +- .../allapps/AllAppsContainerView.java | 19 +++++++- .../allapps/AllAppsSectionDecorator.java | 45 ++++++++++++++----- .../allapps/AlphabeticalAppsList.java | 19 ++++++++ .../launcher3/allapps/FloatingHeaderRow.java | 6 +++ .../launcher3/allapps/FloatingHeaderView.java | 14 ++++++ .../launcher3/allapps/PluginHeaderRow.java | 5 +++ .../search/AllAppsSearchBarController.java | 13 ++++++ .../keyboard/FocusIndicatorHelper.java | 22 ++++++--- 11 files changed, 138 insertions(+), 21 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/AppsDividerView.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/AppsDividerView.java index 7dc7bfcc36..b891120378 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/AppsDividerView.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/AppsDividerView.java @@ -310,4 +310,9 @@ public class AppsDividerView extends View implements StateListener getTypeClass() { return AppsDividerView.class; } + + @Override + public View getFocusedChild() { + return null; + } } diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java index 8a810e3aa4..d3c4c3d62d 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java @@ -169,6 +169,7 @@ public class PredictionRowView extends LinearLayout implements mDecorationHandler.extendBounds(getChildAt(i)); } mDecorationHandler.onDraw(canvas); + mDecorationHandler.onFocusDraw(canvas, getFocusedChild()); } mFocusHelper.draw(canvas); super.dispatchDraw(canvas); @@ -183,7 +184,7 @@ public class PredictionRowView extends LinearLayout implements @Override public boolean shouldDraw() { - return getVisibility() != GONE; + return getVisibility() == VISIBLE; } @Override @@ -364,4 +365,9 @@ public class PredictionRowView extends LinearLayout implements public Class getTypeClass() { return PredictionRowView.class; } + + @Override + public View getFocusedChild() { + return getChildAt(0); + } } diff --git a/res/values/colors.xml b/res/values/colors.xml index 9a89dee956..fe9717cd7a 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -35,7 +35,8 @@ #E0E0E0 - #327d7d7d + #32c0c0c0 + #40c0c0c0 #A0C2F9 #6DA1FF diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java index 2d711e6251..af3722a1f8 100644 --- a/src/com/android/launcher3/allapps/AllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java @@ -527,6 +527,22 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo return mViewPager == null ? getActiveRecyclerView() : mViewPager; } + /** + * Returns the ItemInfo of a view that is in focus, ready to be launched by an IME. + */ + public ItemInfo getHighlightedItemInfo() { + View view = getFloatingHeaderView().getFocusedChild(); + if (view != null && view.getTag() instanceof ItemInfo) { + return ((ItemInfo) view.getTag()); + } + if (getActiveRecyclerView().getApps().getFocusedChild() != null) { + // TODO: when new pipelines are included, getSearchResults + // should be supported at recycler view level and not apps list level. + return getActiveRecyclerView().getApps().getFocusedChild().appInfo; + } + return null; + } + public RecyclerViewFastScroller getScrollBar() { AllAppsRecyclerView rv = getActiveRecyclerView(); return rv == null ? null : rv.getScrollbar(); @@ -658,7 +674,8 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo applyPadding(); setupOverlay(); if (FeatureFlags.ENABLE_DEVICE_SEARCH.get()) { - recyclerView.addItemDecoration(new AllAppsSectionDecorator(getApps())); + recyclerView.addItemDecoration(new AllAppsSectionDecorator( + AllAppsContainerView.this)); } } diff --git a/src/com/android/launcher3/allapps/AllAppsSectionDecorator.java b/src/com/android/launcher3/allapps/AllAppsSectionDecorator.java index ac55072d58..a168c06d72 100644 --- a/src/com/android/launcher3/allapps/AllAppsSectionDecorator.java +++ b/src/com/android/launcher3/allapps/AllAppsSectionDecorator.java @@ -21,6 +21,7 @@ import android.graphics.Paint; import android.graphics.RectF; import android.view.View; +import androidx.annotation.Nullable; import androidx.recyclerview.widget.RecyclerView; import com.android.launcher3.R; @@ -34,19 +35,19 @@ import java.util.List; */ public class AllAppsSectionDecorator extends RecyclerView.ItemDecoration { - private final AlphabeticalAppsList mApps; + private final AllAppsContainerView mAppsView; - AllAppsSectionDecorator(AlphabeticalAppsList appsList) { - mApps = appsList; + AllAppsSectionDecorator(AllAppsContainerView appsContainerView) { + mAppsView = appsContainerView; } @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { // Iterate through views in recylerview and draw bounds around views in the same section. // Since views in the same section will follow each other, we can skip to a last view in - // a section to get the bounds of the section without having to iterate on evert item. + // a section to get the bounds of the section without having to iterate on every item. int itemCount = parent.getChildCount(); - List adapterItems = mApps.getAdapterItems(); + List adapterItems = mAppsView.getApps().getAdapterItems(); SectionDecorationHandler lastDecorationHandler = null; int i = 0; while (i < itemCount) { @@ -69,7 +70,6 @@ public class AllAppsSectionDecorator extends RecyclerView.ItemDecoration { i = endIndex; continue; } - } i++; } @@ -78,13 +78,21 @@ public class AllAppsSectionDecorator extends RecyclerView.ItemDecoration { } } - private void drawDecoration(Canvas c, SectionDecorationHandler decorationHandler, View parent) { + private void drawDecoration(Canvas c, SectionDecorationHandler decorationHandler, + RecyclerView parent) { if (decorationHandler == null) return; if (decorationHandler.mIsFullWidth) { decorationHandler.mBounds.left = parent.getPaddingLeft(); decorationHandler.mBounds.right = parent.getWidth() - parent.getPaddingRight(); } decorationHandler.onDraw(c); + if (mAppsView.getFloatingHeaderView().getFocusedChild() == null + && mAppsView.getApps().getFocusedChild() != null) { + int index = mAppsView.getApps().getFocusedChildIndex(); + if (index >= 0 && index < parent.getChildCount()) { + decorationHandler.onFocusDraw(c, parent.getChildAt(index)); + } + } decorationHandler.reset(); } @@ -95,18 +103,21 @@ public class AllAppsSectionDecorator extends RecyclerView.ItemDecoration { protected RectF mBounds = new RectF(); private final boolean mIsFullWidth; private final float mRadius; + + private final int mFocusColor; private final int mFillcolor; - Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); public SectionDecorationHandler(Context context, boolean isFullWidth) { mIsFullWidth = isFullWidth; mFillcolor = context.getColor(R.color.all_apps_section_fill); + mFocusColor = context.getColor(R.color.all_apps_section_focused_item); mRadius = Themes.getDialogCornerRadius(context); } /** - * Extends current bounds to include view + * Extends current bounds to include the view. */ public void extendBounds(View view) { if (mBounds.isEmpty()) { @@ -122,7 +133,7 @@ public class AllAppsSectionDecorator extends RecyclerView.ItemDecoration { } /** - * Draw bounds onto canvas + * Draw bounds onto canvas. */ public void onDraw(Canvas canvas) { mPaint.setColor(mFillcolor); @@ -130,7 +141,19 @@ public class AllAppsSectionDecorator extends RecyclerView.ItemDecoration { } /** - * Reset view bounds to empty + * Draw the bound of the view to the canvas. + */ + public void onFocusDraw(Canvas canvas, @Nullable View view) { + if (view == null) { + return; + } + mPaint.setColor(mFocusColor); + canvas.drawRoundRect(view.getLeft(), view.getTop(), + view.getRight(), view.getBottom(), mRadius, mRadius, mPaint); + } + + /** + * Reset view bounds to empty. */ public void reset() { mBounds.setEmpty(); diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java index 9076f2a650..7379dbed9a 100644 --- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java +++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java @@ -223,6 +223,25 @@ public class AlphabeticalAppsList implements AllAppsStore.OnUpdateListener { return mAdapterItems; } + /** + * Returns the child adapter item with IME launch focus. + */ + public AdapterItem getFocusedChild() { + return mAdapterItems.get(getFocusedChildIndex()); + } + + /** + * Returns the index of the child with IME launch focus. + */ + public int getFocusedChildIndex() { + for (AdapterItem item : mAdapterItems) { + if (item.isCountedForAccessibility()) { + return mAdapterItems.indexOf(item); + } + } + return -1; + } + /** * Returns the number of rows of applications */ diff --git a/src/com/android/launcher3/allapps/FloatingHeaderRow.java b/src/com/android/launcher3/allapps/FloatingHeaderRow.java index f899587bc0..e357f61dac 100644 --- a/src/com/android/launcher3/allapps/FloatingHeaderRow.java +++ b/src/com/android/launcher3/allapps/FloatingHeaderRow.java @@ -16,6 +16,7 @@ package com.android.launcher3.allapps; import android.graphics.Rect; +import android.view.View; import android.view.animation.Interpolator; import com.android.launcher3.DeviceProfile; @@ -55,4 +56,9 @@ public interface FloatingHeaderRow { void setVerticalScroll(int scroll, boolean isScrolledOut); Class getTypeClass(); + + /** + * Returns a child that has focus to be launched by the IME. + */ + View getFocusedChild(); } diff --git a/src/com/android/launcher3/allapps/FloatingHeaderView.java b/src/com/android/launcher3/allapps/FloatingHeaderView.java index 81e1b94acf..11d3fb995a 100644 --- a/src/com/android/launcher3/allapps/FloatingHeaderView.java +++ b/src/com/android/launcher3/allapps/FloatingHeaderView.java @@ -38,6 +38,7 @@ import com.android.launcher3.DeviceProfile; import com.android.launcher3.Insettable; import com.android.launcher3.R; import com.android.launcher3.anim.PropertySetter; +import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper; import com.android.systemui.plugins.AllAppsRow; import com.android.systemui.plugins.AllAppsRow.OnHeightUpdatedListener; @@ -194,6 +195,19 @@ public class FloatingHeaderView extends LinearLayout implements onHeightUpdated(); } + @Override + public View getFocusedChild() { + if (FeatureFlags.ENABLE_DEVICE_SEARCH.get()) { + for (FloatingHeaderRow row : mAllRows) { + if (row.hasVisibleContent() && row.shouldDraw()) { + return row.getFocusedChild(); + } + } + return null; + } + return super.getFocusedChild(); + } + public void setup(AllAppsContainerView.AdapterHolder[] mAH, boolean tabsHidden) { for (FloatingHeaderRow row : mAllRows) { row.setup(this, mAllRows, tabsHidden); diff --git a/src/com/android/launcher3/allapps/PluginHeaderRow.java b/src/com/android/launcher3/allapps/PluginHeaderRow.java index 3089b18150..cf7142c338 100644 --- a/src/com/android/launcher3/allapps/PluginHeaderRow.java +++ b/src/com/android/launcher3/allapps/PluginHeaderRow.java @@ -83,4 +83,9 @@ public class PluginHeaderRow implements FloatingHeaderRow { public Class getTypeClass() { return PluginHeaderRow.class; } + + @Override + public View getFocusedChild() { + return null; + } } \ No newline at end of file diff --git a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java index db94e8b6e8..06faaacd8e 100644 --- a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java +++ b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java @@ -27,8 +27,11 @@ import android.widget.TextView.OnEditorActionListener; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.ExtendedEditText; +import com.android.launcher3.Launcher; import com.android.launcher3.Utilities; import com.android.launcher3.allapps.AlphabeticalAppsList; +import com.android.launcher3.config.FeatureFlags; +import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.util.PackageManagerHelper; import java.util.ArrayList; @@ -101,6 +104,16 @@ public class AllAppsSearchBarController @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (FeatureFlags.ENABLE_DEVICE_SEARCH.get()) { + if (actionId == EditorInfo.IME_ACTION_SEARCH) { + ItemInfo info = Launcher.getLauncher(mLauncher).getAppsView() + .getHighlightedItemInfo(); + if (info != null) { + return mLauncher.startActivitySafely(v, info.getIntent(), info); + } + } + } + // Skip if it's not the right action if (actionId != EditorInfo.IME_ACTION_SEARCH) { return false; diff --git a/src/com/android/launcher3/keyboard/FocusIndicatorHelper.java b/src/com/android/launcher3/keyboard/FocusIndicatorHelper.java index c50189c1c2..ae7ad106b8 100644 --- a/src/com/android/launcher3/keyboard/FocusIndicatorHelper.java +++ b/src/com/android/launcher3/keyboard/FocusIndicatorHelper.java @@ -32,6 +32,8 @@ import android.view.View; import android.view.View.OnFocusChangeListener; import com.android.launcher3.R; +import com.android.launcher3.config.FeatureFlags; +import com.android.launcher3.util.Themes; /** * A helper class to draw background of a focused view. @@ -93,6 +95,7 @@ public abstract class FocusIndicatorHelper implements private ObjectAnimator mCurrentAnimation; private float mAlpha; + private float mRadius; public FocusIndicatorHelper(View container) { mContainer = container; @@ -104,6 +107,9 @@ public abstract class FocusIndicatorHelper implements setAlpha(0); mShift = 0; + if (FeatureFlags.ENABLE_DEVICE_SEARCH.get()) { + mRadius = Themes.getDialogCornerRadius(container.getContext()); + } } protected void setAlpha(float alpha) { @@ -129,13 +135,15 @@ public abstract class FocusIndicatorHelper implements } public void draw(Canvas c) { - if (mAlpha > 0) { - Rect newRect = getDrawRect(); - if (newRect != null) { - mDirtyRect.set(newRect); - c.drawRect(mDirtyRect, mPaint); - mIsDirty = true; - } + if (mAlpha <= 0) return; + + Rect newRect = getDrawRect(); + if (newRect != null) { + mDirtyRect.set(newRect); + c.drawRoundRect((float) mDirtyRect.left, (float) mDirtyRect.top, + (float) mDirtyRect.right, (float) mDirtyRect.bottom, + mRadius, mRadius, mPaint); + mIsDirty = true; } }