From 2385fc4e209dc0311d8a544281d9d6c68a5cc720 Mon Sep 17 00:00:00 2001 From: Ats Jenk Date: Fri, 10 Dec 2021 15:56:00 -0800 Subject: [PATCH] Refactor BadgedImageView to extend FrameLayout BadgedImageView was extending ImageView and drew the badge icon on top of the bubble icon. This makes it difficult to animate the app icon among other things. Refactored BadgedImageView to extend FrameLayout. Moved bubble icon and app icon into separate ImageView's that are added to the FrameLayout. Bug: 162857077 Test: compared layout before and after the refactor Test: enabled RTL layout, compared layout before and after the refactor Change-Id: I18645549a156d7d78eacc223fca39657346e08dd --- .../wm/shell/bubbles/BadgedImageView.java | 72 ++++++++++++------- .../wm/shell/bubbles/BubbleOverflow.kt | 8 +-- 2 files changed, 52 insertions(+), 28 deletions(-) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java index d92e2ccc77bdc..686fbbfd6f7cd 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java @@ -15,23 +15,22 @@ */ package com.android.wm.shell.bubbles; -import static android.graphics.Paint.ANTI_ALIAS_FLAG; -import static android.graphics.Paint.DITHER_FLAG; -import static android.graphics.Paint.FILTER_BITMAP_FLAG; - +import android.annotation.DrawableRes; import android.annotation.Nullable; import android.content.Context; +import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Outline; -import android.graphics.Paint; -import android.graphics.PaintFlagsDrawFilter; import android.graphics.Path; import android.graphics.Rect; +import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.util.PathParser; +import android.view.Gravity; import android.view.View; import android.view.ViewOutlineProvider; +import android.widget.FrameLayout; import android.widget.ImageView; import com.android.launcher3.icons.DotRenderer; @@ -47,7 +46,7 @@ import java.util.EnumSet; * Badge = the icon associated with the app that created this bubble, this will show work profile * badge if appropriate. */ -public class BadgedImageView extends ImageView { +public class BadgedImageView extends FrameLayout { /** Same value as Launcher3 dot code */ public static final float WHITE_SCRIM_ALPHA = 0.54f; @@ -74,6 +73,9 @@ public class BadgedImageView extends ImageView { private final EnumSet mDotSuppressionFlags = EnumSet.of(SuppressionFlag.FLYOUT_VISIBLE); + private final ImageView mBubbleIcon; + private final ImageView mAppIcon; + private float mDotScale = 0f; private float mAnimatingToDotScale = 0f; private boolean mDotIsAnimating = false; @@ -86,7 +88,6 @@ public class BadgedImageView extends ImageView { private DotRenderer.DrawParams mDrawParams; private int mDotColor; - private Paint mPaint = new Paint(ANTI_ALIAS_FLAG); private Rect mTempBounds = new Rect(); public BadgedImageView(Context context) { @@ -104,6 +105,17 @@ public class BadgedImageView extends ImageView { public BadgedImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); + + mBubbleIcon = new ImageView(context); + addView(mBubbleIcon); + mAppIcon = new ImageView(context); + addView(mAppIcon); + + final TypedArray ta = mContext.obtainStyledAttributes(attrs, new int[]{android.R.attr.src}, + defStyleAttr, defStyleRes); + mBubbleIcon.setImageResource(ta.getResourceId(0, 0)); + ta.recycle(); + mDrawParams = new DotRenderer.DrawParams(); setFocusable(true); @@ -135,7 +147,6 @@ public class BadgedImageView extends ImageView { public void showDotAndBadge(boolean onLeft) { removeDotSuppressionFlag(BadgedImageView.SuppressionFlag.BEHIND_STACK); animateDotBadgePositions(onLeft); - } public void hideDotAndBadge(boolean onLeft) { @@ -149,6 +160,7 @@ public class BadgedImageView extends ImageView { */ public void setRenderedBubble(BubbleViewProvider bubble) { mBubble = bubble; + mBubbleIcon.setImageBitmap(bubble.getBubbleIcon()); if (mDotSuppressionFlags.contains(SuppressionFlag.BEHIND_STACK)) { hideBadge(); } else { @@ -176,6 +188,20 @@ public class BadgedImageView extends ImageView { mDotRenderer.draw(canvas, mDrawParams); } + /** + * Set drawable resource shown as the icon + */ + public void setIconImageResource(@DrawableRes int drawable) { + mBubbleIcon.setImageResource(drawable); + } + + /** + * Get icon drawable + */ + public Drawable getIconDrawable() { + return mBubbleIcon.getDrawable(); + } + /** Adds a dot suppression flag, updating dot visibility if needed. */ void addDotSuppressionFlag(SuppressionFlag flag) { if (mDotSuppressionFlags.add(flag)) { @@ -279,7 +305,6 @@ public class BadgedImageView extends ImageView { showBadge(); } - /** Whether to draw the dot in onDraw(). */ private boolean shouldDrawDot() { // Always render the dot if it's animating, since it could be animating out. Otherwise, show @@ -325,29 +350,28 @@ public class BadgedImageView extends ImageView { void showBadge() { Bitmap badge = mBubble.getAppBadge(); if (badge == null) { - setImageBitmap(mBubble.getBubbleIcon()); + mAppIcon.setVisibility(GONE); return; } - Canvas bubbleCanvas = new Canvas(); - Bitmap noBadgeBubble = mBubble.getBubbleIcon(); - Bitmap bubble = noBadgeBubble.copy(noBadgeBubble.getConfig(), /* isMutable */ true); - bubbleCanvas.setDrawFilter(new PaintFlagsDrawFilter(DITHER_FLAG, FILTER_BITMAP_FLAG)); - bubbleCanvas.setBitmap(bubble); - final int bubbleSize = bubble.getWidth(); + final int bubbleSize = mBubble.getBubbleIcon().getWidth(); final int badgeSize = (int) (ICON_BADGE_SCALE * bubbleSize); - Rect dest = new Rect(); + + FrameLayout.LayoutParams appIconParams = (LayoutParams) mAppIcon.getLayoutParams(); + appIconParams.height = badgeSize; + appIconParams.width = badgeSize; if (mOnLeft) { - dest.set(0, bubbleSize - badgeSize, badgeSize, bubbleSize); + appIconParams.gravity = Gravity.BOTTOM | Gravity.LEFT; } else { - dest.set(bubbleSize - badgeSize, bubbleSize - badgeSize, bubbleSize, bubbleSize); + appIconParams.gravity = Gravity.BOTTOM | Gravity.RIGHT; } - bubbleCanvas.drawBitmap(badge, null /* src */, dest, mPaint); - bubbleCanvas.setBitmap(null); - setImageBitmap(bubble); + mAppIcon.setLayoutParams(appIconParams); + + mAppIcon.setImageBitmap(badge); + mAppIcon.setVisibility(VISIBLE); } void hideBadge() { - setImageBitmap(mBubble.getBubbleIcon()); + mAppIcon.setVisibility(GONE); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt index 5161092fb96cb..a175929cf4987 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt @@ -66,7 +66,7 @@ class BubbleOverflow( updateResources() getExpandedView()?.applyThemeAttrs() // Apply inset and new style to fresh icon drawable. - getIconView()?.setImageResource(R.drawable.bubble_ic_overflow_button) + getIconView()?.setIconImageResource(R.drawable.bubble_ic_overflow_button) updateBtnTheme() } @@ -89,19 +89,19 @@ class BubbleOverflow( dotColor = colorAccent val shapeColor = res.getColor(android.R.color.system_accent1_1000) - overflowBtn?.drawable?.setTint(shapeColor) + overflowBtn?.iconDrawable?.setTint(shapeColor) val iconFactory = BubbleIconFactory(context) // Update bitmap - val fg = InsetDrawable(overflowBtn?.drawable, overflowIconInset) + val fg = InsetDrawable(overflowBtn?.iconDrawable, overflowIconInset) bitmap = iconFactory.createBadgedIconBitmap( AdaptiveIconDrawable(ColorDrawable(colorAccent), fg)).icon // Update dot path dotPath = PathParser.createPathFromPathData( res.getString(com.android.internal.R.string.config_icon_mask)) - val scale = iconFactory.normalizer.getScale(iconView!!.drawable, + val scale = iconFactory.normalizer.getScale(iconView!!.iconDrawable, null /* outBounds */, null /* path */, null /* outMaskShape */) val radius = BadgedImageView.DEFAULT_PATH_SIZE / 2f val matrix = Matrix()