Merge "Move BadgeRenderer to iconloader library" into ub-launcher3-master

This commit is contained in:
TreeHugger Robot 2018-12-01 00:37:30 +00:00 committed by Android (Google) Code Review
commit ddf3592803
4 changed files with 71 additions and 61 deletions

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.android.launcher3.badge; package com.android.launcher3.icons;
import static android.graphics.Paint.ANTI_ALIAS_FLAG; import static android.graphics.Paint.ANTI_ALIAS_FLAG;
import static android.graphics.Paint.FILTER_BITMAP_FLAG; import static android.graphics.Paint.FILTER_BITMAP_FLAG;
@ -26,24 +26,22 @@ import android.graphics.Paint;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.Rect; import android.graphics.Rect;
import android.util.Log; import android.util.Log;
import android.view.ViewDebug;
import com.android.launcher3.icons.ShadowGenerator;
/** /**
* Contains parameters necessary to draw a badge for an icon (e.g. the size of the badge). * Used to draw a notification dot on top of an icon.
* @see BadgeInfo for the data to draw
*/ */
public class BadgeRenderer { public class DotRenderer {
private static final String TAG = "BadgeRenderer"; private static final String TAG = "DotRenderer";
// The badge sizes are defined as percentages of the app icon size. // The dot size is defined as a percentage of the app icon size.
private static final float SIZE_PERCENTAGE = 0.38f; private static final float SIZE_PERCENTAGE = 0.38f;
// Extra scale down of the dot // Extra scale down of the dot
private static final float DOT_SCALE = 0.6f; private static final float DOT_SCALE = 0.6f;
// Used to expand the width of the badge for each additional digit. // Offset the dot slightly away from the icon if there's space.
private static final float OFFSET_PERCENTAGE = 0.02f; private static final float OFFSET_PERCENTAGE = 0.02f;
private final float mDotCenterOffset; private final float mDotCenterOffset;
@ -54,7 +52,7 @@ public class BadgeRenderer {
private final Bitmap mBackgroundWithShadow; private final Bitmap mBackgroundWithShadow;
private final float mBitmapOffset; private final float mBitmapOffset;
public BadgeRenderer(int iconSizePx) { public DotRenderer(int iconSizePx) {
mDotCenterOffset = SIZE_PERCENTAGE * iconSizePx; mDotCenterOffset = SIZE_PERCENTAGE * iconSizePx;
mOffset = (int) (OFFSET_PERCENTAGE * iconSizePx); mOffset = (int) (OFFSET_PERCENTAGE * iconSizePx);
@ -68,33 +66,47 @@ public class BadgeRenderer {
} }
/** /**
* Draw a circle in the top right corner of the given bounds, and draw * Draw a circle on top of the canvas according to the given params.
* {@link BadgeInfo#getNotificationCount()} on top of the circle.
* @param color The color (based on the icon) to use for the badge.
* @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( public void draw(Canvas canvas, DrawParams params) {
Canvas canvas, int color, Rect iconBounds, float badgeScale, Point spaceForOffset) { if (params == null) {
if (iconBounds == null || spaceForOffset == null) {
Log.e(TAG, "Invalid null argument(s) passed in call to draw."); Log.e(TAG, "Invalid null argument(s) passed in call to draw.");
return; return;
} }
canvas.save(); canvas.save();
// We draw the badge relative to its center. // We draw the dot relative to its center.
float badgeCenterX = iconBounds.right - mDotCenterOffset / 2; float dotCenterX = params.leftAlign
float badgeCenterY = iconBounds.top + mDotCenterOffset / 2; ? params.iconBounds.left + mDotCenterOffset / 2
: params.iconBounds.right - mDotCenterOffset / 2;
float dotCenterY = params.iconBounds.top + mDotCenterOffset / 2;
int offsetX = Math.min(mOffset, spaceForOffset.x); int offsetX = Math.min(mOffset, params.spaceForOffset.x);
int offsetY = Math.min(mOffset, spaceForOffset.y); int offsetY = Math.min(mOffset, params.spaceForOffset.y);
canvas.translate(badgeCenterX + offsetX, badgeCenterY - offsetY); canvas.translate(dotCenterX + offsetX, dotCenterY - offsetY);
canvas.scale(badgeScale, badgeScale); canvas.scale(params.scale, params.scale);
mCirclePaint.setColor(Color.BLACK); mCirclePaint.setColor(Color.BLACK);
canvas.drawBitmap(mBackgroundWithShadow, mBitmapOffset, mBitmapOffset, mCirclePaint); canvas.drawBitmap(mBackgroundWithShadow, mBitmapOffset, mBitmapOffset, mCirclePaint);
mCirclePaint.setColor(color); mCirclePaint.setColor(params.color);
canvas.drawCircle(0, 0, mCircleRadius, mCirclePaint); canvas.drawCircle(0, 0, mCircleRadius, mCirclePaint);
canvas.restore(); canvas.restore();
} }
public static class DrawParams {
/** The color (possibly based on the icon) to use for the dot. */
@ViewDebug.ExportedProperty(category = "notification dot", formatToHexString = true)
public int color;
/** The bounds of the icon that the dot is drawn on top of. */
@ViewDebug.ExportedProperty(category = "notification dot")
public Rect iconBounds = new Rect();
/** The progress of the animation, from 0 to 1. */
@ViewDebug.ExportedProperty(category = "notification dot")
public float scale;
/** Overrides internally calculated offset if specified value is smaller. */
@ViewDebug.ExportedProperty(category = "notification dot")
public Point spaceForOffset = new Point();
/** Whether the dot should align to the top left of the icon rather than the top right. */
@ViewDebug.ExportedProperty(category = "notification dot")
public boolean leftAlign;
}
} }

View File

@ -27,7 +27,6 @@ import android.content.res.TypedArray;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
@ -44,11 +43,11 @@ import android.widget.TextView;
import com.android.launcher3.Launcher.OnResumeCallback; import com.android.launcher3.Launcher.OnResumeCallback;
import com.android.launcher3.badge.BadgeInfo; import com.android.launcher3.badge.BadgeInfo;
import com.android.launcher3.badge.BadgeRenderer;
import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.graphics.DrawableFactory; import com.android.launcher3.graphics.DrawableFactory;
import com.android.launcher3.graphics.IconPalette; import com.android.launcher3.graphics.IconPalette;
import com.android.launcher3.graphics.PreloadIconDrawable; import com.android.launcher3.graphics.PreloadIconDrawable;
import com.android.launcher3.icons.DotRenderer;
import com.android.launcher3.icons.IconCache.IconLoadRequest; import com.android.launcher3.icons.IconCache.IconLoadRequest;
import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver; import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
import com.android.launcher3.model.PackageItemInfo; import com.android.launcher3.model.PackageItemInfo;
@ -74,12 +73,12 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
= new Property<BubbleTextView, Float>(Float.TYPE, "badgeScale") { = new Property<BubbleTextView, Float>(Float.TYPE, "badgeScale") {
@Override @Override
public Float get(BubbleTextView bubbleTextView) { public Float get(BubbleTextView bubbleTextView) {
return bubbleTextView.mBadgeScale; return bubbleTextView.mDotParams.scale;
} }
@Override @Override
public void set(BubbleTextView bubbleTextView, Float value) { public void set(BubbleTextView bubbleTextView, Float value) {
bubbleTextView.mBadgeScale = value; bubbleTextView.mDotParams.scale = value;
bubbleTextView.invalidate(); bubbleTextView.invalidate();
} }
}; };
@ -117,14 +116,11 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
@ViewDebug.ExportedProperty(category = "launcher") @ViewDebug.ExportedProperty(category = "launcher")
private BadgeInfo mBadgeInfo; private BadgeInfo mBadgeInfo;
private BadgeRenderer mBadgeRenderer; private DotRenderer mDotRenderer;
private int mBadgeColor; @ViewDebug.ExportedProperty(category = "launcher", deepExport = true)
@ViewDebug.ExportedProperty(category = "launcher") private DotRenderer.DrawParams mDotParams;
private float mBadgeScale;
private Animator mBadgeScaleAnim; private Animator mBadgeScaleAnim;
private boolean mForceHideBadge; private boolean mForceHideBadge;
private Point mTempSpaceForBadgeOffset = new Point();
private Rect mTempIconBounds = new Rect();
@ViewDebug.ExportedProperty(category = "launcher") @ViewDebug.ExportedProperty(category = "launcher")
private boolean mStayPressed; private boolean mStayPressed;
@ -176,6 +172,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
mLongPressHelper = new CheckLongPressHelper(this); mLongPressHelper = new CheckLongPressHelper(this);
mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this); mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this);
mDotParams = new DotRenderer.DrawParams();
setEllipsize(TruncateAt.END); setEllipsize(TruncateAt.END);
setAccessibilityDelegate(mActivity.getAccessibilityDelegate()); setAccessibilityDelegate(mActivity.getAccessibilityDelegate());
setTextAlpha(1f); setTextAlpha(1f);
@ -193,9 +191,9 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
*/ */
public void reset() { public void reset() {
mBadgeInfo = null; mBadgeInfo = null;
mBadgeColor = Color.TRANSPARENT; mDotParams.color = Color.TRANSPARENT;
cancelBadgeScaleAnim(); cancelBadgeScaleAnim();
mBadgeScale = 0f; mDotParams.scale = 0f;
mForceHideBadge = false; mForceHideBadge = false;
} }
@ -259,7 +257,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
private void applyIconAndLabel(ItemInfoWithIcon info) { private void applyIconAndLabel(ItemInfoWithIcon info) {
FastBitmapDrawable iconDrawable = DrawableFactory.INSTANCE.get(getContext()) FastBitmapDrawable iconDrawable = DrawableFactory.INSTANCE.get(getContext())
.newIcon(getContext(), info); .newIcon(getContext(), info);
mBadgeColor = IconPalette.getMutedColor(info.iconColor, 0.54f); mDotParams.color = IconPalette.getMutedColor(info.iconColor, 0.54f);
setIcon(iconDrawable); setIcon(iconDrawable);
setText(info.title); setText(info.title);
@ -383,14 +381,13 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
* @param canvas The canvas to draw to. * @param canvas The canvas to draw to.
*/ */
protected void drawBadgeIfNecessary(Canvas canvas) { protected void drawBadgeIfNecessary(Canvas canvas) {
if (!mForceHideBadge && (hasBadge() || mBadgeScale > 0)) { if (!mForceHideBadge && (hasBadge() || mDotParams.scale > 0)) {
getIconBounds(mTempIconBounds); getIconBounds(mDotParams.iconBounds);
mTempSpaceForBadgeOffset.set((getWidth() - mIconSize) / 2, getPaddingTop()); mDotParams.spaceForOffset.set((getWidth() - mIconSize) / 2, getPaddingTop());
final int scrollX = getScrollX(); final int scrollX = getScrollX();
final int scrollY = getScrollY(); final int scrollY = getScrollY();
canvas.translate(scrollX, scrollY); canvas.translate(scrollX, scrollY);
mBadgeRenderer.draw(canvas, mBadgeColor, mTempIconBounds, mBadgeScale, mDotRenderer.draw(canvas, mDotParams);
mTempSpaceForBadgeOffset);
canvas.translate(-scrollX, -scrollY); canvas.translate(-scrollX, -scrollY);
} }
} }
@ -545,14 +542,14 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
mBadgeInfo = mActivity.getBadgeInfoForItem(itemInfo); mBadgeInfo = mActivity.getBadgeInfoForItem(itemInfo);
boolean isBadged = mBadgeInfo != null; boolean isBadged = mBadgeInfo != null;
float newBadgeScale = isBadged ? 1f : 0; float newBadgeScale = isBadged ? 1f : 0;
mBadgeRenderer = mActivity.getDeviceProfile().mBadgeRenderer; mDotRenderer = mActivity.getDeviceProfile().mDotRenderer;
if (wasBadged || isBadged) { if (wasBadged || isBadged) {
// Animate when a badge is first added or when it is removed. // Animate when a badge is first added or when it is removed.
if (animate && (wasBadged ^ isBadged) && isShown()) { if (animate && (wasBadged ^ isBadged) && isShown()) {
animateBadgeScale(newBadgeScale); animateBadgeScale(newBadgeScale);
} else { } else {
cancelBadgeScaleAnim(); cancelBadgeScaleAnim();
mBadgeScale = newBadgeScale; mDotParams.scale = newBadgeScale;
invalidate(); invalidate();
} }
} }

View File

@ -29,7 +29,7 @@ import android.view.Surface;
import android.view.WindowManager; import android.view.WindowManager;
import com.android.launcher3.CellLayout.ContainerType; import com.android.launcher3.CellLayout.ContainerType;
import com.android.launcher3.badge.BadgeRenderer; import com.android.launcher3.icons.DotRenderer;
import com.android.launcher3.icons.IconNormalizer; import com.android.launcher3.icons.IconNormalizer;
public class DeviceProfile { public class DeviceProfile {
@ -129,7 +129,7 @@ public class DeviceProfile {
private boolean mIsSeascape; private boolean mIsSeascape;
// Icon badges // Icon badges
public BadgeRenderer mBadgeRenderer; public DotRenderer mDotRenderer;
public DeviceProfile(Context context, InvariantDeviceProfile inv, public DeviceProfile(Context context, InvariantDeviceProfile inv,
Point minSize, Point maxSize, Point minSize, Point maxSize,
@ -233,7 +233,7 @@ public class DeviceProfile {
updateWorkspacePadding(); updateWorkspacePadding();
// This is done last, after iconSizePx is calculated above. // This is done last, after iconSizePx is calculated above.
mBadgeRenderer = new BadgeRenderer(iconSizePx); mDotRenderer = new DotRenderer(iconSizePx);
} }
public DeviceProfile copy(Context context) { public DeviceProfile copy(Context context) {

View File

@ -24,7 +24,6 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator; import android.animation.ObjectAnimator;
import android.content.Context; import android.content.Context;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.util.AttributeSet; import android.util.AttributeSet;
@ -57,11 +56,11 @@ import com.android.launcher3.StylusEventHelper;
import com.android.launcher3.Utilities; import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace; import com.android.launcher3.Workspace;
import com.android.launcher3.anim.Interpolators; import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.badge.BadgeRenderer;
import com.android.launcher3.badge.FolderBadgeInfo; import com.android.launcher3.badge.FolderBadgeInfo;
import com.android.launcher3.dragndrop.BaseItemDragListener; import com.android.launcher3.dragndrop.BaseItemDragListener;
import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.dragndrop.DragView; import com.android.launcher3.dragndrop.DragView;
import com.android.launcher3.icons.DotRenderer;
import com.android.launcher3.touch.ItemClickHandler; import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.util.Thunk; import com.android.launcher3.util.Thunk;
import com.android.launcher3.widget.PendingAddShortcutInfo; import com.android.launcher3.widget.PendingAddShortcutInfo;
@ -111,11 +110,11 @@ public class FolderIcon extends FrameLayout implements FolderListener {
@ViewDebug.ExportedProperty(category = "launcher", deepExport = true) @ViewDebug.ExportedProperty(category = "launcher", deepExport = true)
private FolderBadgeInfo mBadgeInfo = new FolderBadgeInfo(); private FolderBadgeInfo mBadgeInfo = new FolderBadgeInfo();
private BadgeRenderer mBadgeRenderer; private DotRenderer mDotRenderer;
@ViewDebug.ExportedProperty(category = "launcher") @ViewDebug.ExportedProperty(category = "launcher", deepExport = true)
private DotRenderer.DrawParams mDotParams;
private float mBadgeScale; private float mBadgeScale;
private Animator mBadgeScaleAnim; private Animator mBadgeScaleAnim;
private Point mTempSpaceForBadgeOffset = new Point();
private static final Property<FolderIcon, Float> BADGE_SCALE_PROPERTY private static final Property<FolderIcon, Float> BADGE_SCALE_PROPERTY
= new Property<FolderIcon, Float>(Float.TYPE, "badgeScale") { = new Property<FolderIcon, Float>(Float.TYPE, "badgeScale") {
@ -147,6 +146,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
mPreviewLayoutRule = new ClippedFolderIconLayoutRule(); mPreviewLayoutRule = new ClippedFolderIconLayoutRule();
mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
mPreviewItemManager = new PreviewItemManager(this); mPreviewItemManager = new PreviewItemManager(this);
mDotParams = new DotRenderer.DrawParams();
} }
public static FolderIcon fromXml(int resId, Launcher launcher, ViewGroup group, public static FolderIcon fromXml(int resId, Launcher launcher, ViewGroup group,
@ -174,7 +174,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
icon.setOnClickListener(ItemClickHandler.INSTANCE); icon.setOnClickListener(ItemClickHandler.INSTANCE);
icon.mInfo = folderInfo; icon.mInfo = folderInfo;
icon.mLauncher = launcher; icon.mLauncher = launcher;
icon.mBadgeRenderer = launcher.getDeviceProfile().mBadgeRenderer; icon.mDotRenderer = launcher.getDeviceProfile().mDotRenderer;
icon.setContentDescription(launcher.getString(R.string.folder_name_format, folderInfo.title)); icon.setContentDescription(launcher.getString(R.string.folder_name_format, folderInfo.title));
Folder folder = Folder.fromXml(launcher); Folder folder = Folder.fromXml(launcher);
folder.setDragController(launcher.getDragController()); folder.setDragController(launcher.getDragController());
@ -492,13 +492,14 @@ public class FolderIcon extends FrameLayout implements FolderListener {
public void drawBadge(Canvas canvas) { public void drawBadge(Canvas canvas) {
if ((mBadgeInfo != null && mBadgeInfo.hasBadge()) || mBadgeScale > 0) { if ((mBadgeInfo != null && mBadgeInfo.hasBadge()) || mBadgeScale > 0) {
BubbleTextView.getIconBounds(this, mTempBounds, mLauncher.getDeviceProfile().iconSizePx); Rect iconBounds = mDotParams.iconBounds;
BubbleTextView.getIconBounds(this, iconBounds, mLauncher.getDeviceProfile().iconSizePx);
// If we are animating to the accepting state, animate the badge out. // If we are animating to the accepting state, animate the badge out.
float badgeScale = Math.max(0, mBadgeScale - mBackground.getScaleProgress()); mDotParams.scale = Math.max(0, mBadgeScale - mBackground.getScaleProgress());
mTempSpaceForBadgeOffset.set(getWidth() - mTempBounds.right, mTempBounds.top); mDotParams.spaceForOffset.set(getWidth() - iconBounds.right, iconBounds.top);
mBadgeRenderer.draw(canvas, mBackground.getBadgeColor(), mTempBounds, mDotParams.color = mBackground.getBadgeColor();
badgeScale, mTempSpaceForBadgeOffset); mDotRenderer.draw(canvas, mDotParams);
} }
} }