Handle IME selection focus for ENABLE_DEVICE_SEARCH
Bug: 162861289 Change-Id: I15e4eae09be2aa9f89a5157fd74c95e91e64bc53
This commit is contained in:
parent
70a556da1d
commit
5dd045bec6
|
@ -310,4 +310,9 @@ public class AppsDividerView extends View implements StateListener<LauncherState
|
|||
public Class<AppsDividerView> getTypeClass() {
|
||||
return AppsDividerView.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getFocusedChild() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<PredictionRowView> getTypeClass() {
|
||||
return PredictionRowView.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getFocusedChild() {
|
||||
return getChildAt(0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,8 @@
|
|||
|
||||
<color name="icon_background">#E0E0E0</color> <!-- Gray 300 -->
|
||||
|
||||
<color name="all_apps_section_fill">#327d7d7d</color>
|
||||
<color name="all_apps_section_fill">#32c0c0c0</color>
|
||||
<color name="all_apps_section_focused_item">#40c0c0c0</color>
|
||||
|
||||
<color name="gesture_tutorial_ripple_color">#A0C2F9</color> <!-- Light Blue -->
|
||||
<color name="gesture_tutorial_fake_task_view_color">#6DA1FF</color> <!-- Light Blue -->
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<AlphabeticalAppsList.AdapterItem> adapterItems = mApps.getAdapterItems();
|
||||
List<AlphabeticalAppsList.AdapterItem> 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();
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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<? extends FloatingHeaderRow> getTypeClass();
|
||||
|
||||
/**
|
||||
* Returns a child that has focus to be launched by the IME.
|
||||
*/
|
||||
View getFocusedChild();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -83,4 +83,9 @@ public class PluginHeaderRow implements FloatingHeaderRow {
|
|||
public Class<PluginHeaderRow> getTypeClass() {
|
||||
return PluginHeaderRow.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getFocusedChild() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue