diff --git a/res/values/colors.xml b/res/values/colors.xml index 9ac248a8e6..52c61e71a6 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -33,6 +33,7 @@ #757575 #1DE9B6 + #1DE9B6 #E0E0E0 #FFFFFF diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index ea1ee9e6d3..b0e8b1e81f 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -100,7 +100,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver { private BadgeInfo mBadgeInfo; private BadgeRenderer mBadgeRenderer; - private IconPalette mIconPalette; + private IconPalette mBadgePalette; private float mBadgeScale; private boolean mForceHideBadge; private Point mTempSpaceForBadgeOffset = new Point(); @@ -463,7 +463,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver { final int scrollX = getScrollX(); final int scrollY = getScrollY(); canvas.translate(scrollX, scrollY); - mBadgeRenderer.draw(canvas, mBadgeInfo, mTempIconBounds, mBadgeScale, + mBadgeRenderer.draw(canvas, mBadgePalette, mBadgeInfo, mTempIconBounds, mBadgeScale, mTempSpaceForBadgeOffset); canvas.translate(-scrollX, -scrollY); } @@ -597,7 +597,10 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver { float newBadgeScale = isBadged ? 1f : 0; mBadgeRenderer = mLauncher.getDeviceProfile().mBadgeRenderer; if (wasBadged || isBadged) { - mIconPalette = ((FastBitmapDrawable) mIcon).getIconPalette(); + mBadgePalette = IconPalette.getBadgePalette(getResources()); + if (mBadgePalette == null) { + mBadgePalette = ((FastBitmapDrawable) mIcon).getIconPalette(); + } // Animate when a badge is first added or when it is removed. if (animate && (wasBadged ^ isBadged) && isShown()) { ObjectAnimator.ofFloat(this, BADGE_SCALE_PROPERTY, newBadgeScale).start(); @@ -609,6 +612,10 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver { } } + public IconPalette getBadgePalette() { + return mBadgePalette; + } + /** * Sets the icon for this view based on the layout direction. */ diff --git a/src/com/android/launcher3/FastBitmapDrawable.java b/src/com/android/launcher3/FastBitmapDrawable.java index a096a1ddf0..199baaf588 100644 --- a/src/com/android/launcher3/FastBitmapDrawable.java +++ b/src/com/android/launcher3/FastBitmapDrawable.java @@ -124,7 +124,7 @@ public class FastBitmapDrawable extends Drawable { public IconPalette getIconPalette() { if (mIconPalette == null) { mIconPalette = IconPalette.fromDominantColor(Utilities - .findDominantColorByHue(mBitmap, 20)); + .findDominantColorByHue(mBitmap, 20), true /* desaturateBackground */); } return mIconPalette; } diff --git a/src/com/android/launcher3/badge/BadgeRenderer.java b/src/com/android/launcher3/badge/BadgeRenderer.java index adde4a2fc4..ba1977af44 100644 --- a/src/com/android/launcher3/badge/BadgeRenderer.java +++ b/src/com/android/launcher3/badge/BadgeRenderer.java @@ -63,7 +63,6 @@ public class BadgeRenderer { private final Paint mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); private final SparseArray mBackgroundsWithShadow; - private final IconPalette mIconPalette; public BadgeRenderer(Context context, int iconSizePx) { mContext = context; @@ -83,25 +82,24 @@ public class BadgeRenderer { mTextHeight = tempTextHeight.height(); mBackgroundsWithShadow = new SparseArray<>(3); - - mIconPalette = IconPalette.fromDominantColor(context.getColor(R.color.badge_color)); } /** * Draw a circle in the top right corner of the given bounds, and draw * {@link BadgeInfo#getNotificationCount()} on top of the circle. + * @param palette The colors (based on the icon) to use for the badge. * @param badgeInfo Contains data to draw on the badge. Could be null if we are animating out. * @param iconBounds The bounds of the icon being badged. * @param badgeScale The progress of the animation, from 0 to 1. * @param spaceForOffset How much space is available to offset the badge up and to the right. */ - public void draw(Canvas canvas, @Nullable BadgeInfo badgeInfo, + public void draw(Canvas canvas, IconPalette palette, @Nullable BadgeInfo badgeInfo, Rect iconBounds, float badgeScale, Point spaceForOffset) { - mTextPaint.setColor(mIconPalette.textColor); + mTextPaint.setColor(palette.textColor); IconDrawer iconDrawer = badgeInfo != null && badgeInfo.isIconLarge() ? mLargeIconDrawer : mSmallIconDrawer; Shader icon = badgeInfo == null ? null : badgeInfo.getNotificationIconForBadge( - mContext, mIconPalette.backgroundColor, mSize, iconDrawer.mPadding); + mContext, palette.backgroundColor, mSize, iconDrawer.mPadding); String notificationCount = badgeInfo == null ? "0" : String.valueOf(badgeInfo.getNotificationCount()); int numChars = notificationCount.length(); @@ -127,7 +125,7 @@ public class BadgeRenderer { canvas.translate(badgeCenterX + offsetX, badgeCenterY - offsetY); canvas.scale(badgeScale, badgeScale); // Prepare the background and shadow and possible stacking effect. - mBackgroundPaint.setColorFilter(mIconPalette.backgroundColorMatrixFilter); + mBackgroundPaint.setColorFilter(palette.backgroundColorMatrixFilter); int backgroundWithShadowSize = backgroundWithShadow.getHeight(); // Same as width. boolean shouldStack = !isDot && badgeInfo != null && badgeInfo.getNotificationKeys().size() > 1; @@ -149,7 +147,7 @@ public class BadgeRenderer { -backgroundWithShadowSize / 2, mBackgroundPaint); iconDrawer.drawIcon(icon, canvas); } else if (isDot) { - mBackgroundPaint.setColorFilter(mIconPalette.saturatedBackgroundColorMatrixFilter); + mBackgroundPaint.setColorFilter(palette.saturatedBackgroundColorMatrixFilter); canvas.drawBitmap(backgroundWithShadow, -backgroundWithShadowSize / 2, -backgroundWithShadowSize / 2, mBackgroundPaint); } diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java index 236bf24a18..b793f491ec 100644 --- a/src/com/android/launcher3/folder/FolderIcon.java +++ b/src/com/android/launcher3/folder/FolderIcon.java @@ -78,6 +78,7 @@ import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.dragndrop.DragView; import com.android.launcher3.util.Themes; +import com.android.launcher3.graphics.IconPalette; import com.android.launcher3.util.Thunk; import com.android.launcher3.widget.PendingAddShortcutInfo; @@ -933,7 +934,8 @@ public class FolderIcon extends FrameLayout implements FolderListener { // If we are animating to the accepting state, animate the badge out. float badgeScale = Math.max(0, mBadgeScale - mBackground.getScaleProgress()); mTempSpaceForBadgeOffset.set(getWidth() - mTempBounds.right, mTempBounds.top); - mBadgeRenderer.draw(canvas, mBadgeInfo, mTempBounds, + IconPalette badgePalette = IconPalette.getFolderBadgePalette(getResources()); + mBadgeRenderer.draw(canvas, badgePalette, mBadgeInfo, mTempBounds, badgeScale, mTempSpaceForBadgeOffset); } } diff --git a/src/com/android/launcher3/graphics/IconPalette.java b/src/com/android/launcher3/graphics/IconPalette.java index 750f4deec5..6e01ed5038 100644 --- a/src/com/android/launcher3/graphics/IconPalette.java +++ b/src/com/android/launcher3/graphics/IconPalette.java @@ -18,9 +18,12 @@ package com.android.launcher3.graphics; import android.app.Notification; import android.content.Context; +import android.content.res.Resources; import android.graphics.Color; import android.graphics.ColorMatrix; import android.graphics.ColorMatrixColorFilter; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v4.graphics.ColorUtils; import android.util.Log; @@ -35,11 +38,12 @@ public class IconPalette { private static final boolean DEBUG = false; private static final String TAG = "IconPalette"; - public static final IconPalette FOLDER_ICON_PALETTE = new IconPalette(Color.parseColor("#BDC1C6")); - private static final float MIN_PRELOAD_COLOR_SATURATION = 0.2f; private static final float MIN_PRELOAD_COLOR_LIGHTNESS = 0.6f; + private static IconPalette sBadgePalette; + private static IconPalette sFolderBadgePalette; + public final int dominantColor; public final int backgroundColor; public final ColorMatrixColorFilter backgroundColorMatrixFilter; @@ -47,15 +51,19 @@ public class IconPalette { public final int textColor; public final int secondaryColor; - private IconPalette(int color) { + private IconPalette(int color, boolean desaturateBackground) { dominantColor = color; - backgroundColor = dominantColor; + backgroundColor = desaturateBackground ? getMutedColor(dominantColor, 0.87f) : dominantColor; ColorMatrix backgroundColorMatrix = new ColorMatrix(); Themes.setColorScaleOnMatrix(backgroundColor, backgroundColorMatrix); backgroundColorMatrixFilter = new ColorMatrixColorFilter(backgroundColorMatrix); - // Get slightly more saturated background color. - Themes.setColorScaleOnMatrix(getMutedColor(dominantColor, 0.54f), backgroundColorMatrix); - saturatedBackgroundColorMatrixFilter = new ColorMatrixColorFilter(backgroundColorMatrix); + if (!desaturateBackground) { + saturatedBackgroundColorMatrixFilter = backgroundColorMatrixFilter; + } else { + // Get slightly more saturated background color. + Themes.setColorScaleOnMatrix(getMutedColor(dominantColor, 0.54f), backgroundColorMatrix); + saturatedBackgroundColorMatrixFilter = new ColorMatrixColorFilter(backgroundColorMatrix); + } textColor = getTextColorForBackground(backgroundColor); secondaryColor = getLowContrastColor(backgroundColor); } @@ -78,8 +86,35 @@ public class IconPalette { return result; } - public static IconPalette fromDominantColor(int dominantColor) { - return new IconPalette(dominantColor); + public static IconPalette fromDominantColor(int dominantColor, boolean desaturateBackground) { + return new IconPalette(dominantColor, desaturateBackground); + } + + /** + * Returns an IconPalette based on the badge_color in colors.xml. + * If that color is Color.TRANSPARENT, then returns null instead. + */ + public static @Nullable IconPalette getBadgePalette(Resources resources) { + int badgeColor = resources.getColor(R.color.badge_color); + if (badgeColor == Color.TRANSPARENT) { + // Colors will be extracted per app icon, so a static palette won't work. + return null; + } + if (sBadgePalette == null) { + sBadgePalette = fromDominantColor(badgeColor, false); + } + return sBadgePalette; + } + + /** + * Returns an IconPalette based on the folder_badge_color in colors.xml. + */ + public static @NonNull IconPalette getFolderBadgePalette(Resources resources) { + if (sFolderBadgePalette == null) { + int badgeColor = resources.getColor(R.color.folder_badge_color); + sFolderBadgePalette = fromDominantColor(badgeColor, false); + } + return sFolderBadgePalette; } /** diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java index 131abbad92..5463ef7722 100644 --- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java +++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java @@ -49,7 +49,6 @@ import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.BubbleTextView; import com.android.launcher3.DragSource; import com.android.launcher3.DropTarget; -import com.android.launcher3.FastBitmapDrawable; import com.android.launcher3.ItemInfo; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAnimUtils; @@ -628,9 +627,7 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra ItemInfo itemInfo = (ItemInfo) mOriginalIcon.getTag(); BadgeInfo badgeInfo = mLauncher.getPopupDataProvider().getBadgeInfoForItem(itemInfo); if (mNotificationItemView != null && badgeInfo != null) { - IconPalette palette = mOriginalIcon.getIcon() instanceof FastBitmapDrawable - ? ((FastBitmapDrawable) mOriginalIcon.getIcon()).getIconPalette() - : null; + IconPalette palette = mOriginalIcon.getBadgePalette(); mNotificationItemView.updateHeader(badgeInfo.getNotificationCount(), palette); } }