Merge "Add group highlighting to AA+ result" into sc-dev

This commit is contained in:
Hyunyoung Song
2021-02-19 20:48:37 +00:00
committed by Android (Google) Code Review
8 changed files with 102 additions and 129 deletions
@@ -130,7 +130,7 @@ public class PredictionRowView extends LinearLayout implements
if (FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
mDecorationHandler = new AllAppsSectionDecorator.SectionDecorationHandler(getContext(),
false);
false, 0, true, true);
}
updateVisibility();
@@ -164,7 +164,7 @@ public class PredictionRowView extends LinearLayout implements
for (int i = 0; i < childrenCount; i++) {
mDecorationHandler.extendBounds(getChildAt(i));
}
mDecorationHandler.onDraw(canvas);
mDecorationHandler.onGroupDraw(canvas);
mDecorationHandler.onFocusDraw(canvas, getFocusedChild());
mLauncher.getAppsView().getActiveRecyclerView().invalidateItemDecorations();
}
+3 -1
View File
@@ -254,11 +254,13 @@
<!-- Search related -->
<dimen name="search_hero_title_size">16sp</dimen>
<dimen name="search_hero_subtitle_size">15sp</dimen>
<dimen name="search_hero_subtitle_size">14sp</dimen>
<dimen name="search_hero_inline_button_size">12sp</dimen>
<dimen name="search_settings_icon_size">36dp</dimen>
<dimen name="search_settings_icon_vertical_offset">16dp</dimen>
<dimen name="search_line_spacing">4dp</dimen>
<dimen name="search_decoration_corner_radius">28dp</dimen>
<dimen name="search_decoration_padding">1dp</dimen>
<!-- Taskbar related (placeholders to compile in Launcher3 without Quickstep) -->
<dimen name="taskbar_size">0dp</dimen>
+1 -14
View File
@@ -53,7 +53,6 @@ import androidx.annotation.UiThread;
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 @@ import java.text.NumberFormat;
* 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 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
setCompoundDrawables(null, newIcon, null, null);
}
}
@Override
public void decorate(int color) {
mHighlightColor = color;
invalidate();
}
@Override
public void removeDecoration() {
mHighlightColor = Color.TRANSPARENT;
invalidate();
}
}
@@ -42,8 +42,7 @@ import com.android.launcher3.BaseDraggingActivity;
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 @@ public class AllAppsGridAdapter extends
// 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 @@ public class AllAppsGridAdapter extends
@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 @@ public class AllAppsGridAdapter extends
@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
@@ -18,16 +18,18 @@ package com.android.launcher3.allapps;
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 @@ public class AllAppsSectionDecorator extends RecyclerView.ItemDecoration {
@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 @@ public class AllAppsSectionDecorator extends RecyclerView.ItemDecoration {
* 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 @@ public class AllAppsSectionDecorator extends RecyclerView.ItemDecoration {
/**
* 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 @@ public class AllAppsSectionDecorator extends RecyclerView.ItemDecoration {
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 @@ public class AllAppsSectionDecorator extends RecyclerView.ItemDecoration {
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);
}
}
@@ -20,7 +20,7 @@ import android.content.Context;
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 @@ public class AlphabeticalAppsList implements AllAppsStore.OnUpdateListener {
}
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 @@ public class AlphabeticalAppsList implements AllAppsStore.OnUpdateListener {
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 @@ public class AlphabeticalAppsList implements AllAppsStore.OnUpdateListener {
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()) {
@@ -37,14 +37,14 @@ public class AppsSearchPipeline implements SearchPipeline {
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 @@ public class AppsSearchPipeline implements SearchPipeline {
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);
}
@@ -18,37 +18,30 @@ package com.android.launcher3.allapps.search;
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 @@ public class SearchSectionInfo {
mDecorationHandler = sectionDecorationHandler;
}
public SectionDecorationHandler getDecorationHandler() {
return mDecorationHandler;
}