Add group highlighting to AA+ result
Bug: 180071886
Test: manual
Change-Id: Id1cc3d7400e1a7fe41af272d689aa9315030b420
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index e5a4335..ee4d7ec 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -53,7 +53,6 @@
import com.android.launcher3.Launcher.OnResumeCallback;
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
-import com.android.launcher3.allapps.AllAppsSectionDecorator;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dot.DotInfo;
import com.android.launcher3.dragndrop.DraggableView;
@@ -84,7 +83,7 @@
* too aggressive.
*/
public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, OnResumeCallback,
- IconLabelDotView, DraggableView, Reorderable, AllAppsSectionDecorator.SelfDecoratingView {
+ IconLabelDotView, DraggableView, Reorderable {
private static final int DISPLAY_WORKSPACE = 0;
private static final int DISPLAY_ALL_APPS = 1;
@@ -954,16 +953,4 @@
setCompoundDrawables(null, newIcon, null, null);
}
}
-
- @Override
- public void decorate(int color) {
- mHighlightColor = color;
- invalidate();
- }
-
- @Override
- public void removeDecoration() {
- mHighlightColor = Color.TRANSPARENT;
- invalidate();
- }
}
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index 715c142..5030c5e 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -42,8 +42,7 @@
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.R;
import com.android.launcher3.allapps.search.SearchAdapterProvider;
-import com.android.launcher3.allapps.search.SearchSectionInfo;
-import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.allapps.search.SectionDecorationInfo;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.util.PackageManagerHelper;
@@ -109,7 +108,7 @@
// The index of this app not including sections
public int appIndex = -1;
// Search section associated to result
- public SearchSectionInfo searchSectionInfo = null;
+ public SectionDecorationInfo sectionDecorationInfo = null;
/**
* Factory method for AppIcon AdapterItem
@@ -372,10 +371,6 @@
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
- if (FeatureFlags.ENABLE_DEVICE_SEARCH.get()
- && holder.itemView instanceof AllAppsSectionDecorator.SelfDecoratingView) {
- ((AllAppsSectionDecorator.SelfDecoratingView) holder.itemView).removeDecoration();
- }
switch (holder.getItemViewType()) {
case VIEW_TYPE_ICON:
AdapterItem adapterItem = mApps.getAdapterItems().get(position);
@@ -409,10 +404,6 @@
@Override
public void onViewRecycled(@NonNull ViewHolder holder) {
super.onViewRecycled(holder);
- if (!FeatureFlags.ENABLE_DEVICE_SEARCH.get()) return;
- if (holder.itemView instanceof AllAppsSectionDecorator.SelfDecoratingView) {
- ((AllAppsSectionDecorator.SelfDecoratingView) holder.itemView).removeDecoration();
- }
}
@Override
diff --git a/src/com/android/launcher3/allapps/AllAppsSectionDecorator.java b/src/com/android/launcher3/allapps/AllAppsSectionDecorator.java
index 6c95992..176dce6 100644
--- a/src/com/android/launcher3/allapps/AllAppsSectionDecorator.java
+++ b/src/com/android/launcher3/allapps/AllAppsSectionDecorator.java
@@ -18,16 +18,18 @@
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
+import android.graphics.Path;
import android.graphics.RectF;
import android.view.View;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.graphics.ColorUtils;
import androidx.recyclerview.widget.RecyclerView;
import com.android.launcher3.R;
import com.android.launcher3.allapps.AllAppsGridAdapter.AppsGridLayoutManager;
-import com.android.launcher3.allapps.search.SearchSectionInfo;
+import com.android.launcher3.allapps.search.SectionDecorationInfo;
import com.android.launcher3.util.Themes;
import java.util.List;
@@ -45,52 +47,51 @@
@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 every item.
- int itemCount = parent.getChildCount();
List<AllAppsGridAdapter.AdapterItem> adapterItems = mAppsView.getApps().getAdapterItems();
- SectionDecorationHandler lastDecorationHandler = null;
- int i = 0;
- while (i < itemCount) {
+ boolean drawFallbackFocusedView = true;
+ for (int i = 0; i < parent.getChildCount(); i++) {
View view = parent.getChildAt(i);
- if (view instanceof SelfDecoratingView) {
- ((SelfDecoratingView) view).removeDecoration();
- }
int position = parent.getChildAdapterPosition(view);
AllAppsGridAdapter.AdapterItem adapterItem = adapterItems.get(position);
- if (adapterItem.searchSectionInfo != null) {
- SearchSectionInfo sectionInfo = adapterItem.searchSectionInfo;
- int endIndex = Math.min(i + sectionInfo.getPosEnd() - position, itemCount - 1);
+ if (adapterItem.sectionDecorationInfo != null) {
+ SectionDecorationInfo sectionInfo = adapterItem.sectionDecorationInfo;
SectionDecorationHandler decorationHandler = sectionInfo.getDecorationHandler();
- if (decorationHandler != lastDecorationHandler && lastDecorationHandler != null) {
- drawDecoration(c, lastDecorationHandler, parent);
- }
- lastDecorationHandler = decorationHandler;
if (decorationHandler != null) {
decorationHandler.extendBounds(view);
- }
-
- if (endIndex > i) {
- i = endIndex;
- continue;
+ if (sectionInfo.isFocusedView()) {
+ decorationHandler.onFocusDraw(c, view);
+ drawFallbackFocusedView = false;
+ } else {
+ decorationHandler.onGroupDraw(c);
+ }
}
}
- i++;
}
- if (lastDecorationHandler != null) {
- drawDecoration(c, lastDecorationHandler, parent);
+ // fallback logic in case none of the SearchTarget is labeled as focused item
+ if (drawFallbackFocusedView) {
+ for (int i = 0; i < parent.getChildCount(); i++) {
+ View view = parent.getChildAt(i);
+ int position = parent.getChildAdapterPosition(view);
+ AllAppsGridAdapter.AdapterItem adapterItem = adapterItems.get(position);
+ if (adapterItem.sectionDecorationInfo != null) {
+ SectionDecorationInfo sectionInfo = adapterItem.sectionDecorationInfo;
+ SectionDecorationHandler decorationHandler = sectionInfo.getDecorationHandler();
+ if (decorationHandler != null) {
+ drawDecoration(c, decorationHandler, parent);
+ }
+ }
+ }
}
}
- private void drawDecoration(Canvas c, SectionDecorationHandler decorationHandler,
- RecyclerView parent) {
- if (decorationHandler == null) return;
+ // Fallback logic in case non of the SearchTarget is labeled as focused item.
+ private void drawDecoration(@NonNull Canvas c,
+ @NonNull SectionDecorationHandler decorationHandler,
+ @NonNull RecyclerView parent) {
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();
@@ -109,23 +110,41 @@
* Handles grouping and drawing of items in the same all apps sections.
*/
public static class SectionDecorationHandler {
- private static final int FILL_ALPHA = 0;
-
protected RectF mBounds = new RectF();
private final boolean mIsFullWidth;
private final float mRadius;
- protected int mFocusColor;
- protected int mFillcolor;
+ protected final int mFocusColor; // main focused item color
+ protected final int mFillcolor; // grouping color
+
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ private final boolean mIsTopRound;
+ private final boolean mIsBottomRound;
+ private float [] mCorners;
+ private float mFillSpacing;
+ public SectionDecorationHandler(Context context, boolean isFullWidth, int fillAlpha,
+ boolean isTopRound, boolean isBottomRound) {
- public SectionDecorationHandler(Context context, boolean isFullWidth) {
mIsFullWidth = isFullWidth;
int endScrim = Themes.getColorBackground(context);
- mFillcolor = ColorUtils.setAlphaComponent(endScrim, FILL_ALPHA);
- mFocusColor = endScrim;
- mRadius = Themes.getDialogCornerRadius(context);
+ mFillcolor = ColorUtils.setAlphaComponent(endScrim, fillAlpha);
+ mFocusColor = ColorUtils.setAlphaComponent(endScrim, fillAlpha);
+
+ mIsTopRound = isTopRound;
+ mIsBottomRound = isBottomRound;
+
+ mRadius = context.getResources().getDimensionPixelSize(
+ R.dimen.search_decoration_corner_radius);
+ mFillSpacing = context.getResources().getDimensionPixelSize(
+ R.dimen.search_decoration_padding);
+ mCorners = new float[]{
+ mIsTopRound ? mRadius : 0, mIsTopRound ? mRadius : 0, // Top left radius in px
+ mIsTopRound ? mRadius : 0, mIsTopRound ? mRadius : 0, // Top right radius in px
+ mIsBottomRound ? mRadius : 0, mIsBottomRound ? mRadius : 0, // Bottom right
+ mIsBottomRound ? mRadius : 0, mIsBottomRound ? mRadius : 0 // Bottom left
+ };
+
}
/**
@@ -147,9 +166,9 @@
/**
* Draw bounds onto canvas.
*/
- public void onDraw(Canvas canvas) {
+ public void onGroupDraw(Canvas canvas) {
mPaint.setColor(mFillcolor);
- canvas.drawRoundRect(mBounds, mRadius, mRadius, mPaint);
+ onDraw(canvas);
}
/**
@@ -159,13 +178,20 @@
if (view == null) {
return;
}
- if (view instanceof SelfDecoratingView) {
- ((SelfDecoratingView) view).decorate(mFocusColor);
- return;
- }
mPaint.setColor(mFocusColor);
- canvas.drawRoundRect(view.getLeft(), view.getTop(),
- view.getRight(), view.getBottom(), mRadius, mRadius, mPaint);
+ mBounds.set(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
+ onDraw(canvas);
+ }
+
+
+ private void onDraw(Canvas canvas) {
+ final Path path = new Path();
+ RectF finalBounds = new RectF(mBounds.left + mFillSpacing,
+ mBounds.top + mFillSpacing,
+ mBounds.right - mFillSpacing,
+ mBounds.bottom - mFillSpacing);
+ path.addRoundRect(finalBounds, mCorners, Path.Direction.CW);
+ canvas.drawPath(path, mPaint);
}
/**
@@ -175,19 +201,4 @@
mBounds.setEmpty();
}
}
-
- /**
- * An interface for a view to draw highlight indicator
- */
- public interface SelfDecoratingView {
- /**
- * Removes decorations drawing if focus is acquired by another view
- */
- void removeDecoration();
-
- /**
- * Draws highlight indicator on view.
- */
- void decorate(int focusColor);
- }
}
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index 1dc10fe..123ace7 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -20,7 +20,7 @@
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem;
-import com.android.launcher3.allapps.search.SearchSectionInfo;
+import com.android.launcher3.allapps.search.SectionDecorationInfo;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.util.ItemInfoMatcher;
@@ -201,20 +201,11 @@
}
void updateSearchAdapterItems(ArrayList<AdapterItem> list, int offset) {
- SearchSectionInfo lastSection = null;
for (int i = 0; i < list.size(); i++) {
AdapterItem adapterItem = list.get(i);
adapterItem.position = offset + i;
mAdapterItems.add(adapterItem);
- if (adapterItem.searchSectionInfo != lastSection) {
- if (adapterItem.searchSectionInfo != null) {
- adapterItem.searchSectionInfo.setPosStart(adapterItem.position);
- }
- if (lastSection != null) {
- lastSection.setPosEnd(adapterItem.position - 1);
- }
- lastSection = adapterItem.searchSectionInfo;
- }
+
if (adapterItem.isCountedForAccessibility()) {
mAccessibilityResultsCount++;
}
@@ -295,16 +286,16 @@
mFastScrollerSections.clear();
mAdapterItems.clear();
- SearchSectionInfo appSection = new SearchSectionInfo();
+ SectionDecorationInfo appSection = new SectionDecorationInfo();
appSection.setDecorationHandler(
- new AllAppsSectionDecorator.SectionDecorationHandler(mLauncher, true));
+ new AllAppsSectionDecorator.SectionDecorationHandler(mLauncher, true,
+ 0, false, false));
// Recreate the filtered and sectioned apps (for convenience for the grid layout) from the
// ordered set of sections
if (!hasFilter()) {
mAccessibilityResultsCount = mApps.size();
- appSection.setPosStart(position);
for (AppInfo info : mApps) {
String sectionName = info.sectionName;
@@ -321,11 +312,10 @@
lastFastScrollerSectionInfo.fastScrollToItem = appItem;
}
if (FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
- appItem.searchSectionInfo = appSection;
+ appItem.sectionDecorationInfo = appSection;
}
mAdapterItems.add(appItem);
}
- appSection.setPosEnd(mApps.isEmpty() ? appSection.getPosStart() : position - 1);
} else {
updateSearchAdapterItems(mSearchResults, 0);
if (!FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
diff --git a/src/com/android/launcher3/allapps/search/AppsSearchPipeline.java b/src/com/android/launcher3/allapps/search/AppsSearchPipeline.java
index 84688e1..f9fb22e 100644
--- a/src/com/android/launcher3/allapps/search/AppsSearchPipeline.java
+++ b/src/com/android/launcher3/allapps/search/AppsSearchPipeline.java
@@ -37,14 +37,14 @@
private static final int MAX_RESULTS_COUNT = 5;
- private final SearchSectionInfo mSearchSectionInfo;
+ private final SectionDecorationInfo mSearchSectionInfo;
private final LauncherAppState mLauncherAppState;
public AppsSearchPipeline(Context context, LauncherAppState launcherAppState) {
mLauncherAppState = launcherAppState;
- mSearchSectionInfo = new SearchSectionInfo();
+ mSearchSectionInfo = new SectionDecorationInfo();
mSearchSectionInfo.setDecorationHandler(
- new SectionDecorationHandler(context, true));
+ new SectionDecorationHandler(context, true, 0, true, true));
}
@Override
@@ -81,7 +81,7 @@
ArrayList<AdapterItem> items = new ArrayList<>();
for (int i = 0; i < matchingApps.size() && i < MAX_RESULTS_COUNT; i++) {
AdapterItem appItem = AdapterItem.asApp(i, "", matchingApps.get(i), i);
- appItem.searchSectionInfo = mSearchSectionInfo;
+ appItem.sectionDecorationInfo = mSearchSectionInfo;
items.add(appItem);
}
diff --git a/src/com/android/launcher3/allapps/search/SearchSectionInfo.java b/src/com/android/launcher3/allapps/search/SectionDecorationInfo.java
similarity index 73%
rename from src/com/android/launcher3/allapps/search/SearchSectionInfo.java
rename to src/com/android/launcher3/allapps/search/SectionDecorationInfo.java
index 464df68..0b64fca 100644
--- a/src/com/android/launcher3/allapps/search/SearchSectionInfo.java
+++ b/src/com/android/launcher3/allapps/search/SectionDecorationInfo.java
@@ -18,37 +18,30 @@
import com.android.launcher3.allapps.AllAppsSectionDecorator.SectionDecorationHandler;
/**
- * Info class for a search section
+ * Info class for a search section that is primarily used for decoration.
*/
-public class SearchSectionInfo {
+public class SectionDecorationInfo {
+
+ public static final int QUICK_LAUNCH = 1 << 0;
+ public static final int GROUPING = 1 << 1;
private String mSectionId;
+ private boolean mFocused;
private SectionDecorationHandler mDecorationHandler;
- public int getPosStart() {
- return mPosStart;
+ public boolean isFocusedView() {
+ return mFocused;
}
- public void setPosStart(int posStart) {
- mPosStart = posStart;
+ public void setFocusedView(boolean focused) {
+ mFocused = focused;
}
- public int getPosEnd() {
- return mPosEnd;
- }
-
- public void setPosEnd(int posEnd) {
- mPosEnd = posEnd;
- }
-
- private int mPosStart;
- private int mPosEnd;
-
- public SearchSectionInfo() {
+ public SectionDecorationInfo() {
this(null);
}
- public SearchSectionInfo(String sectionId) {
+ public SectionDecorationInfo(String sectionId) {
mSectionId = sectionId;
}
@@ -56,7 +49,6 @@
mDecorationHandler = sectionDecorationHandler;
}
-
public SectionDecorationHandler getDecorationHandler() {
return mDecorationHandler;
}