Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8912b04c authored by Tony Wickham's avatar Tony Wickham
Browse files

Move BadgeRenderer to iconloader library

- Rename BadgeRenderer to DotRenderer
- Move drawing parameters to new class DrawParams
- Add leftAlign param
Change-Id: I69de56c13280ba5e7e1ea3868c23edfac01012e9
parent 6478d4f4
Loading
Loading
Loading
Loading
+39 −27
Original line number Diff line number Diff line
@@ -14,7 +14,7 @@
 * 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.FILTER_BITMAP_FLAG;
@@ -26,24 +26,22 @@ import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.Log;

import com.android.launcher3.icons.ShadowGenerator;
import android.view.ViewDebug;

/**
 * Contains parameters necessary to draw a badge for an icon (e.g. the size of the badge).
 * @see BadgeInfo for the data to draw
 * Used to draw a notification dot on top of an icon.
 */
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;

    // Extra scale down of the dot
    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 final float mDotCenterOffset;
@@ -54,7 +52,7 @@ public class BadgeRenderer {
    private final Bitmap mBackgroundWithShadow;
    private final float mBitmapOffset;

    public BadgeRenderer(int iconSizePx) {
    public DotRenderer(int iconSizePx) {
        mDotCenterOffset = SIZE_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
     * {@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.
     * Draw a circle on top of the canvas according to the given params.
     */
    public void draw(
            Canvas canvas, int color, Rect iconBounds, float badgeScale, Point spaceForOffset) {
        if (iconBounds == null || spaceForOffset == null) {
    public void draw(Canvas canvas, DrawParams params) {
        if (params == null) {
            Log.e(TAG, "Invalid null argument(s) passed in call to draw.");
            return;
        }
        canvas.save();
        // We draw the badge relative to its center.
        float badgeCenterX = iconBounds.right - mDotCenterOffset / 2;
        float badgeCenterY = iconBounds.top + mDotCenterOffset / 2;
        // We draw the dot relative to its center.
        float dotCenterX = params.leftAlign
                ? 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 offsetY = Math.min(mOffset, spaceForOffset.y);
        canvas.translate(badgeCenterX + offsetX, badgeCenterY - offsetY);
        canvas.scale(badgeScale, badgeScale);
        int offsetX = Math.min(mOffset, params.spaceForOffset.x);
        int offsetY = Math.min(mOffset, params.spaceForOffset.y);
        canvas.translate(dotCenterX + offsetX, dotCenterY - offsetY);
        canvas.scale(params.scale, params.scale);

        mCirclePaint.setColor(Color.BLACK);
        canvas.drawBitmap(mBackgroundWithShadow, mBitmapOffset, mBitmapOffset, mCirclePaint);
        mCirclePaint.setColor(color);
        mCirclePaint.setColor(params.color);
        canvas.drawCircle(0, 0, mCircleRadius, mCirclePaint);
        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;
    }
}
+17 −20
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
@@ -44,11 +43,11 @@ import android.widget.TextView;

import com.android.launcher3.Launcher.OnResumeCallback;
import com.android.launcher3.badge.BadgeInfo;
import com.android.launcher3.badge.BadgeRenderer;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.graphics.DrawableFactory;
import com.android.launcher3.graphics.IconPalette;
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.ItemInfoUpdateReceiver;
import com.android.launcher3.model.PackageItemInfo;
@@ -74,12 +73,12 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
            = new Property<BubbleTextView, Float>(Float.TYPE, "badgeScale") {
        @Override
        public Float get(BubbleTextView bubbleTextView) {
            return bubbleTextView.mBadgeScale;
            return bubbleTextView.mDotParams.scale;
        }

        @Override
        public void set(BubbleTextView bubbleTextView, Float value) {
            bubbleTextView.mBadgeScale = value;
            bubbleTextView.mDotParams.scale = value;
            bubbleTextView.invalidate();
        }
    };
@@ -117,14 +116,11 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,

    @ViewDebug.ExportedProperty(category = "launcher")
    private BadgeInfo mBadgeInfo;
    private BadgeRenderer mBadgeRenderer;
    private int mBadgeColor;
    @ViewDebug.ExportedProperty(category = "launcher")
    private float mBadgeScale;
    private DotRenderer mDotRenderer;
    @ViewDebug.ExportedProperty(category = "launcher", deepExport = true)
    private DotRenderer.DrawParams mDotParams;
    private Animator mBadgeScaleAnim;
    private boolean mForceHideBadge;
    private Point mTempSpaceForBadgeOffset = new Point();
    private Rect mTempIconBounds = new Rect();

    @ViewDebug.ExportedProperty(category = "launcher")
    private boolean mStayPressed;
@@ -176,6 +172,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
        mLongPressHelper = new CheckLongPressHelper(this);
        mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this);

        mDotParams = new DotRenderer.DrawParams();

        setEllipsize(TruncateAt.END);
        setAccessibilityDelegate(mActivity.getAccessibilityDelegate());
        setTextAlpha(1f);
@@ -193,9 +191,9 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
     */
    public void reset() {
        mBadgeInfo = null;
        mBadgeColor = Color.TRANSPARENT;
        mDotParams.color = Color.TRANSPARENT;
        cancelBadgeScaleAnim();
        mBadgeScale = 0f;
        mDotParams.scale = 0f;
        mForceHideBadge = false;
    }

@@ -259,7 +257,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
    private void applyIconAndLabel(ItemInfoWithIcon info) {
        FastBitmapDrawable iconDrawable = DrawableFactory.INSTANCE.get(getContext())
                .newIcon(getContext(), info);
        mBadgeColor = IconPalette.getMutedColor(info.iconColor, 0.54f);
        mDotParams.color = IconPalette.getMutedColor(info.iconColor, 0.54f);

        setIcon(iconDrawable);
        setText(info.title);
@@ -383,14 +381,13 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
     * @param canvas The canvas to draw to.
     */
    protected void drawBadgeIfNecessary(Canvas canvas) {
        if (!mForceHideBadge && (hasBadge() || mBadgeScale > 0)) {
            getIconBounds(mTempIconBounds);
            mTempSpaceForBadgeOffset.set((getWidth() - mIconSize) / 2, getPaddingTop());
        if (!mForceHideBadge && (hasBadge() || mDotParams.scale > 0)) {
            getIconBounds(mDotParams.iconBounds);
            mDotParams.spaceForOffset.set((getWidth() - mIconSize) / 2, getPaddingTop());
            final int scrollX = getScrollX();
            final int scrollY = getScrollY();
            canvas.translate(scrollX, scrollY);
            mBadgeRenderer.draw(canvas, mBadgeColor, mTempIconBounds, mBadgeScale,
                    mTempSpaceForBadgeOffset);
            mDotRenderer.draw(canvas, mDotParams);
            canvas.translate(-scrollX, -scrollY);
        }
    }
@@ -545,14 +542,14 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
            mBadgeInfo = mActivity.getBadgeInfoForItem(itemInfo);
            boolean isBadged = mBadgeInfo != null;
            float newBadgeScale = isBadged ? 1f : 0;
            mBadgeRenderer = mActivity.getDeviceProfile().mBadgeRenderer;
            mDotRenderer = mActivity.getDeviceProfile().mDotRenderer;
            if (wasBadged || isBadged) {
                // Animate when a badge is first added or when it is removed.
                if (animate && (wasBadged ^ isBadged) && isShown()) {
                    animateBadgeScale(newBadgeScale);
                } else {
                    cancelBadgeScaleAnim();
                    mBadgeScale = newBadgeScale;
                    mDotParams.scale = newBadgeScale;
                    invalidate();
                }
            }
+3 −3
Original line number Diff line number Diff line
@@ -29,7 +29,7 @@ import android.view.Surface;
import android.view.WindowManager;

import com.android.launcher3.CellLayout.ContainerType;
import com.android.launcher3.badge.BadgeRenderer;
import com.android.launcher3.icons.DotRenderer;
import com.android.launcher3.icons.IconNormalizer;

public class DeviceProfile {
@@ -129,7 +129,7 @@ public class DeviceProfile {
    private boolean mIsSeascape;

    // Icon badges
    public BadgeRenderer mBadgeRenderer;
    public DotRenderer mDotRenderer;

    public DeviceProfile(Context context, InvariantDeviceProfile inv,
            Point minSize, Point maxSize,
@@ -233,7 +233,7 @@ public class DeviceProfile {
        updateWorkspacePadding();

        // This is done last, after iconSizePx is calculated above.
        mBadgeRenderer = new BadgeRenderer(iconSizePx);
        mDotRenderer = new DotRenderer(iconSizePx);
    }

    public DeviceProfile copy(Context context) {
+12 −11
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
@@ -57,11 +56,11 @@ import com.android.launcher3.StylusEventHelper;
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.badge.BadgeRenderer;
import com.android.launcher3.badge.FolderBadgeInfo;
import com.android.launcher3.dragndrop.BaseItemDragListener;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.dragndrop.DragView;
import com.android.launcher3.icons.DotRenderer;
import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.widget.PendingAddShortcutInfo;
@@ -111,11 +110,11 @@ public class FolderIcon extends FrameLayout implements FolderListener {

    @ViewDebug.ExportedProperty(category = "launcher", deepExport = true)
    private FolderBadgeInfo mBadgeInfo = new FolderBadgeInfo();
    private BadgeRenderer mBadgeRenderer;
    @ViewDebug.ExportedProperty(category = "launcher")
    private DotRenderer mDotRenderer;
    @ViewDebug.ExportedProperty(category = "launcher", deepExport = true)
    private DotRenderer.DrawParams mDotParams;
    private float mBadgeScale;
    private Animator mBadgeScaleAnim;
    private Point mTempSpaceForBadgeOffset = new Point();

    private static final Property<FolderIcon, Float> BADGE_SCALE_PROPERTY
            = new Property<FolderIcon, Float>(Float.TYPE, "badgeScale") {
@@ -147,6 +146,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
        mPreviewLayoutRule = new ClippedFolderIconLayoutRule();
        mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
        mPreviewItemManager = new PreviewItemManager(this);
        mDotParams = new DotRenderer.DrawParams();
    }

    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.mInfo = folderInfo;
        icon.mLauncher = launcher;
        icon.mBadgeRenderer = launcher.getDeviceProfile().mBadgeRenderer;
        icon.mDotRenderer = launcher.getDeviceProfile().mDotRenderer;
        icon.setContentDescription(launcher.getString(R.string.folder_name_format, folderInfo.title));
        Folder folder = Folder.fromXml(launcher);
        folder.setDragController(launcher.getDragController());
@@ -492,13 +492,14 @@ public class FolderIcon extends FrameLayout implements FolderListener {

    public void drawBadge(Canvas canvas) {
        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.
            float badgeScale = Math.max(0, mBadgeScale - mBackground.getScaleProgress());
            mTempSpaceForBadgeOffset.set(getWidth() - mTempBounds.right, mTempBounds.top);
            mBadgeRenderer.draw(canvas, mBackground.getBadgeColor(), mTempBounds,
                    badgeScale, mTempSpaceForBadgeOffset);
            mDotParams.scale = Math.max(0, mBadgeScale - mBackground.getScaleProgress());
            mDotParams.spaceForOffset.set(getWidth() - iconBounds.right, iconBounds.top);
            mDotParams.color = mBackground.getBadgeColor();
            mDotRenderer.draw(canvas, mDotParams);
        }
    }