Update icon badges to match spec

- Size defined as percentage of app icon size
- Width changes when there are 2 or 3 digits (round rect)
- Offset slightly away from the app icon
  - Had to move drawing to BubbleTextView instead of
    FastBitmapDrawable
- Hide badge when dragging and while popup is open
- Tweaks for some color/text parameters

Bug: 35744066
Change-Id: Ibb15ca634abaa0729aea637c904c4c6889a58c7c
This commit is contained in:
Tony Wickham
2017-02-24 08:59:36 -08:00
parent 343a77e609
commit 1237df0a7c
10 changed files with 177 additions and 102 deletions

View File

@@ -16,6 +16,7 @@
package com.android.launcher3;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
@@ -23,9 +24,12 @@ import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Property;
import android.util.TypedValue;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -42,6 +46,7 @@ import com.android.launcher3.badge.BadgeRenderer;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.graphics.DrawableFactory;
import com.android.launcher3.graphics.HolographicOutlineHelper;
import com.android.launcher3.graphics.IconPalette;
import com.android.launcher3.graphics.PreloadIconDrawable;
import com.android.launcher3.model.PackageItemInfo;
import com.android.launcher3.popup.PopupContainerWithArrow;
@@ -90,6 +95,28 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver {
@ViewDebug.ExportedProperty(category = "launcher")
private int mTextColor;
private BadgeInfo mBadgeInfo;
private BadgeRenderer mBadgeRenderer;
private IconPalette mIconPalette;
private float mBadgeScale;
private boolean mForceHideBadge;
private Point mTempSpaceForBadgeOffset = new Point();
private Rect mTempIconBounds = new Rect();
private static final Property<BubbleTextView, Float> BADGE_SCALE_PROPERTY
= new Property<BubbleTextView, Float>(Float.TYPE, "badgeScale") {
@Override
public Float get(BubbleTextView bubbleTextView) {
return bubbleTextView.mBadgeScale;
}
@Override
public void set(BubbleTextView bubbleTextView, Float value) {
bubbleTextView.mBadgeScale = value;
bubbleTextView.invalidate();
}
};
@ViewDebug.ExportedProperty(category = "launcher")
private boolean mStayPressed;
@ViewDebug.ExportedProperty(category = "launcher")
@@ -369,6 +396,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver {
public void draw(Canvas canvas) {
if (!mCustomShadowsEnabled) {
super.draw(canvas);
drawBadgeIfNecessary(canvas);
return;
}
@@ -395,6 +423,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver {
if ((getCurrentTextColor() >> 24) == 0) {
getPaint().clearShadowLayer();
super.draw(canvas);
drawBadgeIfNecessary(canvas);
return;
}
@@ -410,6 +439,50 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver {
density * KEY_SHADOW_RADIUS, 0.0f, density * KEY_SHADOW_OFFSET, KEY_SHADOW_COLOR);
super.draw(canvas);
canvas.restore();
drawBadgeIfNecessary(canvas);
}
/**
* Draws the icon badge in the top right corner of the icon bounds.
* @param canvas The canvas to draw to.
*/
private void drawBadgeIfNecessary(Canvas canvas) {
if (!mForceHideBadge && (hasBadge() || mBadgeScale > 0)) {
getIconBounds(mTempIconBounds);
mTempSpaceForBadgeOffset.set((getWidth() - mIconSize) / 2, getPaddingTop());
final int scrollX = getScrollX();
final int scrollY = getScrollY();
canvas.translate(scrollX, scrollY);
mBadgeRenderer.draw(canvas, mIconPalette, mBadgeInfo, mTempIconBounds, mBadgeScale,
mTempSpaceForBadgeOffset);
canvas.translate(-scrollX, -scrollY);
}
}
public void forceHideBadge(boolean forceHideBadge) {
if (mForceHideBadge == forceHideBadge) {
return;
}
mForceHideBadge = forceHideBadge;
if (forceHideBadge) {
invalidate();
} else if (hasBadge()) {
ObjectAnimator.ofFloat(this, BADGE_SCALE_PROPERTY, 0, 1).start();
}
}
private boolean hasBadge() {
return (mBadgeInfo != null && mBadgeInfo.getNotificationCount() > 0);
}
public void getIconBounds(Rect outBounds) {
int top = getPaddingTop();
int left = (getWidth() - mIconSize) / 2;
int right = left + mIconSize;
int bottom = top + mIconSize;
outBounds.set(left, top, right, bottom);
}
@Override
@@ -506,7 +579,22 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver {
if (popup != null) {
popup.updateNotificationHeader(badgeInfo, itemInfo);
}
((FastBitmapDrawable) mIcon).applyIconBadge(badgeInfo, badgeRenderer, animate);
boolean wasBadged = mBadgeInfo != null;
boolean isBadged = badgeInfo != null;
float newBadgeScale = isBadged ? 1f : 0;
mBadgeInfo = badgeInfo;
mBadgeRenderer = badgeRenderer;
if (wasBadged || isBadged) {
mIconPalette = ((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();
} else {
mBadgeScale = newBadgeScale;
invalidate();
}
}
}
}