Setup SearchResultIcon for single cell results
SearchResultIcon will be able to render apps, shortcuts and remote actions. It can also handle its own focused state drawing.
Screenshot: https://screenshot.googleplex.com/C3KgjJtLQTBPgaf
Bug: 170752716
Test: Manual
Change-Id: I460a9c128ea3f5814784e342c5d5fa5b7e310882
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 817d028..6245637 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -17,6 +17,7 @@
package com.android.launcher3;
import static com.android.launcher3.FastBitmapDrawable.newIcon;
+import static com.android.launcher3.graphics.IconShape.getShape;
import static com.android.launcher3.graphics.PreloadIconDrawable.newPendingIcon;
import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
@@ -27,15 +28,18 @@
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
+import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
+import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.os.Process;
import android.text.TextUtils.TruncateAt;
import android.util.AttributeSet;
import android.util.Property;
@@ -50,6 +54,8 @@
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;
import com.android.launcher3.folder.FolderIcon;
@@ -60,6 +66,7 @@
import com.android.launcher3.icons.DotRenderer;
import com.android.launcher3.icons.IconCache.IconLoadRequest;
import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
+import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.ItemInfoWithIcon;
@@ -79,7 +86,7 @@
* too aggressive.
*/
public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, OnResumeCallback,
- IconLabelDotView, DraggableView, Reorderable {
+ IconLabelDotView, DraggableView, Reorderable, AllAppsSectionDecorator.SelfDecoratingView {
private static final int DISPLAY_WORKSPACE = 0;
private static final int DISPLAY_ALL_APPS = 1;
@@ -87,6 +94,8 @@
private static final int DISPLAY_HERO_APP = 5;
private static final int[] STATE_PRESSED = new int[]{android.R.attr.state_pressed};
+ private static final float HIGHLIGHT_SCALE = 1.16f;
+
private final PointF mTranslationForReorderBounce = new PointF(0, 0);
private final PointF mTranslationForReorderPreview = new PointF(0, 0);
@@ -95,6 +104,11 @@
private float mScaleForReorderBounce = 1f;
+ protected final Paint mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ private final Path mHighlightPath = new Path();
+ protected int mHighlightColor = Color.TRANSPARENT;
+ private final BlurMaskFilter mHighlightShadowFilter;
+
private static final Property<BubbleTextView, Float> DOT_SCALE_PROPERTY
= new Property<BubbleTextView, Float>(Float.TYPE, "dotScale") {
@Override
@@ -208,6 +222,11 @@
setEllipsize(TruncateAt.END);
setAccessibilityDelegate(mActivity.getAccessibilityDelegate());
setTextAlpha(1f);
+
+ int shadowSize = context.getResources().getDimensionPixelSize(
+ R.dimen.blur_size_click_shadow);
+ mHighlightShadowFilter = new BlurMaskFilter(shadowSize, BlurMaskFilter.Blur.INNER);
+
}
@Override
@@ -421,8 +440,38 @@
@Override
public void onDraw(Canvas canvas) {
+ if (FeatureFlags.ENABLE_DEVICE_SEARCH.get() && mHighlightColor != Color.TRANSPARENT) {
+ int count = canvas.save();
+ drawFocusHighlight(canvas);
+ canvas.restoreToCount(count);
+ }
super.onDraw(canvas);
- drawDotIfNecessary(canvas);
+ }
+
+ protected void drawFocusHighlight(Canvas canvas) {
+ boolean isBadged = getTag() instanceof ItemInfo && !Process.myUserHandle().equals(
+ ((ItemInfo) getTag()).user);
+ float insetScale = (HIGHLIGHT_SCALE - 1) / 2;
+ canvas.translate(-getIconSize() * insetScale, -insetScale * getIconSize());
+ float outlineSize = getIconSize() * HIGHLIGHT_SCALE;
+ mHighlightPath.reset();
+ mHighlightPaint.reset();
+ getIconBounds(mDotParams.iconBounds);
+ getShape().addToPath(mHighlightPath, mDotParams.iconBounds.left, mDotParams.iconBounds.top,
+ outlineSize / 2);
+ if (isBadged) {
+ float borderSize = outlineSize - getIconSize();
+ float badgeSize = LauncherIcons.getBadgeSizeForIconSize(getIconSize()) + borderSize;
+ float badgeInset = outlineSize - badgeSize;
+ getShape().addToPath(mHighlightPath, mDotParams.iconBounds.left + badgeInset,
+ mDotParams.iconBounds.top + badgeInset, badgeSize / 2);
+ }
+ mHighlightPaint.setMaskFilter(mHighlightShadowFilter);
+ mHighlightPaint.setColor(mDotParams.color);
+ canvas.drawPath(mHighlightPath, mHighlightPaint);
+ mHighlightPaint.setMaskFilter(null);
+ mHighlightPaint.setColor(mHighlightColor);
+ canvas.drawPath(mHighlightPath, mHighlightPaint);
}
/**
@@ -787,10 +836,11 @@
@Override
public SafeCloseable prepareDrawDragView() {
+ int highlightColor = mHighlightColor;
+ mHighlightColor = Color.TRANSPARENT;
resetIconScale();
setForceHideDot(true);
- return () -> {
- };
+ return () -> mHighlightColor = highlightColor;
}
private void resetIconScale() {
@@ -827,4 +877,17 @@
});
iconUpdateAnimation.start();
}
+
+
+ @Override
+ public void decorate(int color) {
+ mHighlightColor = color;
+ invalidate();
+ }
+
+ @Override
+ public void removeDecoration() {
+ mHighlightColor = Color.TRANSPARENT;
+ invalidate();
+ }
}