diff options
author | Tony Wickham <twickham@google.com> | 2017-01-18 22:36:17 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2017-01-18 22:36:17 +0000 |
commit | 197f97bde4368e79b9475749560ab668a29fc552 (patch) | |
tree | 46f25194582af6706b9bcc509f0bcd8c97292e92 /src | |
parent | 8e98cb876f1c913c256ce6d542a1f975f59f1e2e (diff) | |
parent | 9a8d11f930ced4c2706db150b7bbbb21330bd68d (diff) | |
download | android_packages_apps_Trebuchet-197f97bde4368e79b9475749560ab668a29fc552.tar.gz android_packages_apps_Trebuchet-197f97bde4368e79b9475749560ab668a29fc552.tar.bz2 android_packages_apps_Trebuchet-197f97bde4368e79b9475749560ab668a29fc552.zip |
Merge "FastBitmapDrawable can draw an icon badge (notification count)" into ub-launcher3-master
Diffstat (limited to 'src')
-rw-r--r-- | src/com/android/launcher3/BubbleTextView.java | 17 | ||||
-rw-r--r-- | src/com/android/launcher3/DeviceProfile.java | 9 | ||||
-rw-r--r-- | src/com/android/launcher3/FastBitmapDrawable.java | 30 | ||||
-rw-r--r-- | src/com/android/launcher3/Utilities.java | 2 | ||||
-rw-r--r-- | src/com/android/launcher3/Workspace.java | 2 | ||||
-rw-r--r-- | src/com/android/launcher3/badge/BadgeInfo.java | 33 | ||||
-rw-r--r-- | src/com/android/launcher3/badge/BadgeRenderer.java | 70 | ||||
-rw-r--r-- | src/com/android/launcher3/graphics/IconPalette.java | 63 |
8 files changed, 219 insertions, 7 deletions
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index 32c3ac8be..d9e9c7bb0 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -39,6 +39,8 @@ import android.widget.TextView; import com.android.launcher3.IconCache.IconLoadRequest; import com.android.launcher3.IconCache.ItemInfoUpdateReceiver; +import com.android.launcher3.badge.BadgeRenderer; +import com.android.launcher3.badge.BadgeInfo; import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.graphics.DrawableFactory; import com.android.launcher3.graphics.HolographicOutlineHelper; @@ -164,7 +166,7 @@ public class BubbleTextView extends TextView applyIconAndLabel(info.iconBitmap, info); setTag(info); if (promiseStateChanged || info.isPromise()) { - applyState(promiseStateChanged); + applyPromiseState(promiseStateChanged); } } @@ -470,7 +472,7 @@ public class BubbleTextView extends TextView mLongPressHelper.cancelLongPress(); } - public void applyState(boolean promiseStateChanged) { + public void applyPromiseState(boolean promiseStateChanged) { if (getTag() instanceof ShortcutInfo) { ShortcutInfo info = (ShortcutInfo) getTag(); final boolean isPromise = info.isPromise(); @@ -479,8 +481,8 @@ public class BubbleTextView extends TextView info.getInstallProgress() : 0)) : 100; setContentDescription(progressLevel > 0 ? - getContext().getString(R.string.app_downloading_title, info.title, - NumberFormat.getPercentInstance().format(progressLevel * 0.01)) : + getContext().getString(R.string.app_downloading_title, info.title, + NumberFormat.getPercentInstance().format(progressLevel * 0.01)) : getContext().getString(R.string.app_waiting_download_title, info.title)); if (mIcon != null) { @@ -500,6 +502,13 @@ public class BubbleTextView extends TextView } } + public void applyBadgeState(BadgeInfo badgeInfo) { + if (mIcon instanceof FastBitmapDrawable) { + BadgeRenderer badgeRenderer = mLauncher.getDeviceProfile().mBadgeRenderer; + ((FastBitmapDrawable) mIcon).applyIconBadge(badgeInfo, badgeRenderer); + } + } + private Theme getPreloaderTheme() { Object tag = getTag(); int style = ((tag != null) && (tag instanceof ShortcutInfo) && diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index 27afdc03d..34ce92336 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -31,7 +31,7 @@ import android.view.ViewGroup.LayoutParams; import android.widget.FrameLayout; import com.android.launcher3.CellLayout.ContainerType; -import com.android.launcher3.config.FeatureFlags; +import com.android.launcher3.badge.BadgeRenderer; import java.util.ArrayList; @@ -136,6 +136,9 @@ public class DeviceProfile { // Listeners private ArrayList<LauncherLayoutChangeListener> mListeners = new ArrayList<>(); + // Icon badges + public BadgeRenderer mBadgeRenderer; + public DeviceProfile(Context context, InvariantDeviceProfile inv, Point minSize, Point maxSize, int width, int height, boolean isLandscape) { @@ -193,6 +196,10 @@ public class DeviceProfile { hotseatBarBottomPaddingPx = 0; hotseatLandGutterPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_gutter_width); + int badgeSize = res.getDimensionPixelSize(R.dimen.badge_size); + int badgeTextSize = res.getDimensionPixelSize(R.dimen.badge_text_size); + mBadgeRenderer = new BadgeRenderer(badgeSize, badgeTextSize); + // Determine sizes. widthPx = width; heightPx = height; diff --git a/src/com/android/launcher3/FastBitmapDrawable.java b/src/com/android/launcher3/FastBitmapDrawable.java index 0cefc5739..b3e59f99b 100644 --- a/src/com/android/launcher3/FastBitmapDrawable.java +++ b/src/com/android/launcher3/FastBitmapDrawable.java @@ -33,6 +33,10 @@ import android.graphics.drawable.Drawable; import android.util.SparseArray; import android.view.animation.DecelerateInterpolator; +import com.android.launcher3.graphics.IconPalette; +import com.android.launcher3.badge.BadgeRenderer; +import com.android.launcher3.badge.BadgeInfo; + public class FastBitmapDrawable extends Drawable { private static final float DISABLED_DESATURATION = 1f; private static final float DISABLED_BRIGHTNESS = 0.5f; @@ -99,6 +103,10 @@ public class FastBitmapDrawable extends Drawable { private State mState = State.NORMAL; private boolean mIsDisabled; + private BadgeInfo mBadgeInfo; + private BadgeRenderer mBadgeRenderer; + private IconPalette mIconPalette; + // The saturation and brightness are values that are mapped to REDUCED_FILTER_VALUE_SPACE and // as a result, can be used to compose the key for the cached ColorMatrixColorFilters private int mDesaturation = 0; @@ -114,9 +122,21 @@ public class FastBitmapDrawable extends Drawable { setBounds(0, 0, b.getWidth(), b.getHeight()); } + public void applyIconBadge(BadgeInfo badgeInfo, BadgeRenderer badgeRenderer) { + mBadgeInfo = badgeInfo; + mBadgeRenderer = badgeRenderer; + if (mIconPalette == null) { + mIconPalette = IconPalette.fromDominantColor(Utilities + .findDominantColorByHue(mBitmap, 20)); + } + invalidateSelf(); + } + @Override public void draw(Canvas canvas) { drawInternal(canvas); + // Draw the icon badge in the top right corner. + drawBadgeIfNecessary(canvas); } public void drawWithBrightness(Canvas canvas, float brightness) { @@ -130,6 +150,16 @@ public class FastBitmapDrawable extends Drawable { canvas.drawBitmap(mBitmap, null, getBounds(), mPaint); } + protected void drawBadgeIfNecessary(Canvas canvas) { + if (hasBadge()) { + mBadgeRenderer.draw(canvas, mIconPalette, mBadgeInfo, getBounds()); + } + } + + private boolean hasBadge() { + return mBadgeInfo != null && mBadgeInfo.getNotificationCount() != null; + } + @Override public void setColorFilter(ColorFilter cf) { // No op diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index 89ffd315d..8ad0144c3 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -306,7 +306,7 @@ public final class Utilities { * @param bitmap The bitmap to scan * @param samples The approximate max number of samples to use. */ - static int findDominantColorByHue(Bitmap bitmap, int samples) { + public static int findDominantColorByHue(Bitmap bitmap, int samples) { final int height = bitmap.getHeight(); final int width = bitmap.getWidth(); int sampleStride = (int) Math.sqrt((height * width) / samples); diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 103077953..6eb87f2db 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -3971,7 +3971,7 @@ public class Workspace extends PagedView public boolean evaluate(ItemInfo info, View v) { if (info instanceof ShortcutInfo && v instanceof BubbleTextView && updates.contains(info)) { - ((BubbleTextView) v).applyState(false); + ((BubbleTextView) v).applyPromiseState(false /* promiseStateChanged */); } else if (v instanceof PendingAppWidgetHostView && info instanceof LauncherAppWidgetInfo && updates.contains(info)) { diff --git a/src/com/android/launcher3/badge/BadgeInfo.java b/src/com/android/launcher3/badge/BadgeInfo.java new file mode 100644 index 000000000..0a9f87c6e --- /dev/null +++ b/src/com/android/launcher3/badge/BadgeInfo.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.badge; + +/** + * Contains data to be used in an icon badge. + */ +public class BadgeInfo { + + private int mNotificationCount; + + public void setNotificationCount(int count) { + mNotificationCount = count; + } + + public String getNotificationCount() { + return mNotificationCount == 0 ? null : String.valueOf(mNotificationCount); + } +} diff --git a/src/com/android/launcher3/badge/BadgeRenderer.java b/src/com/android/launcher3/badge/BadgeRenderer.java new file mode 100644 index 000000000..238b9188f --- /dev/null +++ b/src/com/android/launcher3/badge/BadgeRenderer.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.badge; + +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.RectF; + +import com.android.launcher3.graphics.IconPalette; + +/** + * Contains parameters necessary to draw a badge for an icon (e.g. the size of the badge). + * @see BadgeInfo for the data to draw + */ +public class BadgeRenderer { + + public int size; + public int textSize; + + private final RectF mBackgroundRect = new RectF(); + private final Paint mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final int mTextHeight; + + public BadgeRenderer(int size, int textSize) { + this.size = size; + this.textSize = textSize; + mTextPaint.setTextAlign(Paint.Align.CENTER); + mTextPaint.setTextSize(textSize); + // Measure the text height. + Rect temp = new Rect(); + mTextPaint.getTextBounds("0", 0, 1, temp); + mTextHeight = temp.height(); + } + + /** + * 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. + * @param iconBounds The bounds of the icon being badged. + */ + public void draw(Canvas canvas, IconPalette palette, BadgeInfo badgeInfo, Rect iconBounds) { + mBackgroundPaint.setColor(palette.backgroundColor); + mTextPaint.setColor(palette.textColor); + mBackgroundRect.set(iconBounds.right - size, iconBounds.top, iconBounds.right, + iconBounds.top + size); + canvas.drawOval(mBackgroundRect, mBackgroundPaint); + String notificationCount = badgeInfo.getNotificationCount(); + canvas.drawText(notificationCount, + mBackgroundRect.centerX(), + mBackgroundRect.centerY() + mTextHeight / 2, + mTextPaint); + } +} diff --git a/src/com/android/launcher3/graphics/IconPalette.java b/src/com/android/launcher3/graphics/IconPalette.java new file mode 100644 index 000000000..dcc5fcb14 --- /dev/null +++ b/src/com/android/launcher3/graphics/IconPalette.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.graphics; + +import android.graphics.Color; +import android.support.v4.graphics.ColorUtils; + +/** + * Contains colors based on the dominant color of an icon. + */ +public class IconPalette { + + public int backgroundColor; + public int textColor; + + public static IconPalette fromDominantColor(int dominantColor) { + IconPalette palette = new IconPalette(); + palette.backgroundColor = getMutedColor(dominantColor); + palette.textColor = getTextColorForBackground(palette.backgroundColor); + return palette; + } + + private static int getMutedColor(int color) { + int alpha = (int) (255 * 0.2f); + return ColorUtils.compositeColors(ColorUtils.setAlphaComponent(color, alpha), Color.WHITE); + } + + private static int getTextColorForBackground(int backgroundColor) { + return getLighterOrDarkerVersionOfColor(backgroundColor, 3f); + } + + private static int getLowContrastColor(int color) { + return getLighterOrDarkerVersionOfColor(color, 1.5f); + } + + private static int getLighterOrDarkerVersionOfColor(int color, float contrastRatio) { + int whiteMinAlpha = ColorUtils.calculateMinimumAlpha(Color.WHITE, color, contrastRatio); + int blackMinAlpha = ColorUtils.calculateMinimumAlpha(Color.BLACK, color, contrastRatio); + int translucentWhiteOrBlack; + if (whiteMinAlpha >= 0) { + translucentWhiteOrBlack = ColorUtils.setAlphaComponent(Color.WHITE, whiteMinAlpha); + } else if (blackMinAlpha >= 0) { + translucentWhiteOrBlack = ColorUtils.setAlphaComponent(Color.BLACK, blackMinAlpha); + } else { + translucentWhiteOrBlack = Color.WHITE; + } + return ColorUtils.compositeColors(translucentWhiteOrBlack, color); + } +} |