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

Commit 3cdda5fa authored by Tony Wickham's avatar Tony Wickham Committed by Android (Google) Code Review
Browse files

Merge "Show notification icon in place of "1" in badge." into ub-launcher3-master

parents db7b8296 a799bed8
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -172,6 +172,8 @@
<!-- Icon badges (with notification counts) -->
    <dimen name="badge_size">24dp</dimen>
    <dimen name="badge_text_size">12dp</dimen>
    <dimen name="badge_small_padding">1dp</dimen>
    <dimen name="badge_large_padding">3dp</dimen>
    <dimen name="notification_icon_size">28dp</dimen>
    <dimen name="notification_footer_icon_size">24dp</dimen>
    <!-- (icon_size - secondary_icon_size) / 2 -->
+1 −3
Original line number Diff line number Diff line
@@ -196,9 +196,7 @@ 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);
        mBadgeRenderer = new BadgeRenderer(context);

        // Determine sizes.
        widthPx = width;
+60 −2
Original line number Diff line number Diff line
@@ -16,6 +16,14 @@

package com.android.launcher3.badge;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;

import com.android.launcher3.notification.NotificationInfo;
import com.android.launcher3.util.PackageUserKey;

@@ -29,12 +37,22 @@ public class BadgeInfo {

    /** Used to link this BadgeInfo to icons on the workspace and all apps */
    private PackageUserKey mPackageUserKey;

    /**
     * The keys of the notifications that this badge represents. These keys can later be
     * used to retrieve {@link NotificationInfo}'s.
     */
    private List<String> mNotificationKeys;

    /** This will only be initialized if the badge should display the notification icon. */
    private NotificationInfo mNotificationInfo;

    /**
     * When retrieving the notification icon, we draw it into this shader, which can be clipped
     * as necessary when drawn in a badge.
     */
    private Shader mNotificationIcon;

    public BadgeInfo(PackageUserKey packageUserKey) {
        mPackageUserKey = packageUserKey;
        mNotificationKeys = new ArrayList<>();
@@ -65,15 +83,55 @@ public class BadgeInfo {
        return mNotificationKeys.size();
    }

    public void setNotificationToShow(@Nullable NotificationInfo notificationInfo) {
        mNotificationInfo = notificationInfo;
        mNotificationIcon = null;
    }

    public boolean hasNotificationToShow() {
        return mNotificationInfo != null;
    }

    /**
     * Returns a shader to set on a Paint that will draw the notification icon in a badge.
     *
     * The shader is cached until {@link #setNotificationToShow(NotificationInfo)} is called.
     */
    public @Nullable Shader getNotificationIconForBadge(Context context, int badgeColor,
            int badgeSize, int badgePadding) {
        if (mNotificationInfo == null) {
            return null;
        }
        if (mNotificationIcon == null) {
            Drawable icon = mNotificationInfo.getIconForBackground(context, badgeColor)
                    .getConstantState().newDrawable();
            int iconSize = badgeSize - badgePadding * 2;
            icon.setBounds(0, 0, iconSize, iconSize);
            Bitmap iconBitmap = Bitmap.createBitmap(badgeSize, badgeSize, Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(iconBitmap);
            canvas.translate(badgePadding, badgePadding);
            icon.draw(canvas);
            mNotificationIcon = new BitmapShader(iconBitmap, Shader.TileMode.CLAMP,
                    Shader.TileMode.CLAMP);
        }
        return mNotificationIcon;
    }

    public boolean isIconLarge() {
        return mNotificationInfo != null && mNotificationInfo.isIconLarge();
    }

    /**
     * Whether newBadge represents the same PackageUserKey as this badge, and icons with
     * this badge should be invalidated. So, for instance, if a badge has 3 notifications
     * and one of those notifications is updated, this method should return false because
     * the badge still says "3" and the contents of those notifications are only retrieved
     * upon long-click. This method always returns true when adding or removing notifications.
     * upon long-click. This method always returns true when adding or removing notifications,
     * or if the badge has a notification icon to show.
     */
    public boolean shouldBeInvalidated(BadgeInfo newBadge) {
        return mPackageUserKey.equals(newBadge.mPackageUserKey)
                && getNotificationCount() != newBadge.getNotificationCount();
                && (getNotificationCount() != newBadge.getNotificationCount()
                    || hasNotificationToShow());
    }
}
+55 −8
Original line number Diff line number Diff line
@@ -16,11 +16,16 @@

package com.android.launcher3.badge;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;

import com.android.launcher3.R;
import com.android.launcher3.graphics.IconPalette;

/**
@@ -31,15 +36,22 @@ public class BadgeRenderer {

    public int size;
    public int textSize;
    public IconDrawer largeIconDrawer;
    public IconDrawer smallIconDrawer;

    private final Context mContext;
    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;
    public BadgeRenderer(Context context) {
        mContext = context;
        Resources res = context.getResources();
        size = res.getDimensionPixelSize(R.dimen.badge_size);
        textSize = res.getDimensionPixelSize(R.dimen.badge_text_size);
        largeIconDrawer = new IconDrawer(res.getDimensionPixelSize(R.dimen.badge_small_padding));
        smallIconDrawer = new IconDrawer(res.getDimensionPixelSize(R.dimen.badge_large_padding));
        mTextPaint.setTextAlign(Paint.Align.CENTER);
        mTextPaint.setTextSize(textSize);
        // Measure the text height.
@@ -61,6 +73,17 @@ public class BadgeRenderer {
        mBackgroundRect.set(iconBounds.right - size, iconBounds.top, iconBounds.right,
                iconBounds.top + size);
        canvas.drawOval(mBackgroundRect, mBackgroundPaint);
        IconDrawer iconDrawer = badgeInfo.isIconLarge() ? largeIconDrawer : smallIconDrawer;
        Shader icon = badgeInfo.getNotificationIconForBadge(mContext, palette.backgroundColor, size,
                iconDrawer.mPadding);
        if (icon != null) {
            // Draw the notification icon with padding.
            canvas.save();
            canvas.translate(mBackgroundRect.left, mBackgroundRect.top);
            iconDrawer.drawIcon(icon, canvas);
            canvas.restore();
        } else {
            // Draw the notification count.
            String notificationCount = String.valueOf(badgeInfo.getNotificationCount());
            canvas.drawText(notificationCount,
                    mBackgroundRect.centerX(),
@@ -68,3 +91,27 @@ public class BadgeRenderer {
                    mTextPaint);
        }
    }

    /** Draws the notification icon with padding of a given size. */
    private class IconDrawer {

        private final int mPadding;
        private final Bitmap mCircleClipBitmap;
        private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG |
                Paint.FILTER_BITMAP_FLAG);

        public IconDrawer(int padding) {
            mPadding = padding;
            mCircleClipBitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ALPHA_8);
            Canvas canvas = new Canvas();
            canvas.setBitmap(mCircleClipBitmap);
            canvas.drawCircle(size / 2, size / 2, size / 2 - padding, mPaint);
        }

        public void drawIcon(Shader icon, Canvas canvas) {
            mPaint.setShader(icon);
            canvas.drawBitmap(mCircleClipBitmap, 0f, 0f, mPaint);
            mPaint.setShader(null);
        }
    }
}
+26 −6
Original line number Diff line number Diff line
@@ -40,6 +40,11 @@ import com.android.launcher3.util.PackageUserKey;
 */
public class NotificationInfo implements View.OnClickListener {

    // TODO: use Notification constants directly.
    public static final int BADGE_ICON_NONE = 0;
    public static final int BADGE_ICON_SMALL = 1;
    public static final int BADGE_ICON_LARGE = 2;

    public final PackageUserKey packageUserKey;
    public final String notificationKey;
    public final CharSequence title;
@@ -48,9 +53,10 @@ public class NotificationInfo implements View.OnClickListener {
    public final boolean autoCancel;
    public final boolean dismissable;

    private final int mBadgeIcon;
    private final Drawable mIconDrawable;
    private boolean mShouldTintIcon;
    private int mIconColor;
    private boolean mIsIconLarge;

    /**
     * Extracts the data that we need from the StatusBarNotification.
@@ -61,17 +67,20 @@ public class NotificationInfo implements View.OnClickListener {
        Notification notification = statusBarNotification.getNotification();
        title = notification.extras.getCharSequence(Notification.EXTRA_TITLE);
        text = notification.extras.getCharSequence(Notification.EXTRA_TEXT);
        mBadgeIcon = BADGE_ICON_LARGE; // TODO: get from the Notification
        // Load the icon. Since it is backed by ashmem, we won't copy the entire bitmap
        // into our process as long as we don't touch it and it exists in systemui.
        Icon icon = notification.getLargeIcon();
        Icon icon = mBadgeIcon == BADGE_ICON_SMALL ? null : notification.getLargeIcon();
        if (icon == null) {
            // Use the small icon.
            icon = notification.getSmallIcon();
            mIconDrawable = icon.loadDrawable(context);
            mIconColor = statusBarNotification.getNotification().color;
            mShouldTintIcon = true;
            mIsIconLarge = false;
        } else {
            // Use the large icon.
            mIconDrawable = icon.loadDrawable(context);
            mShouldTintIcon = false;
            mIsIconLarge = true;
        }
        intent = notification.contentIntent;
        autoCancel = (notification.flags & Notification.FLAG_AUTO_CANCEL) != 0;
@@ -95,7 +104,8 @@ public class NotificationInfo implements View.OnClickListener {
    }

    public Drawable getIconForBackground(Context context, int background) {
        if (!mShouldTintIcon) {
        if (mIsIconLarge) {
            // Only small icons should be tinted.
            return mIconDrawable;
        }
        mIconColor = IconPalette.resolveContrastColor(context, mIconColor, background);
@@ -104,7 +114,17 @@ public class NotificationInfo implements View.OnClickListener {
        // get it set and invalidated properly.
        icon.setTintList(null);
        icon.setTint(mIconColor);
        mShouldTintIcon = false;
        return icon;
    }

    public boolean isIconLarge() {
        return mIsIconLarge;
    }

    public boolean shouldShowIconInBadge() {
        // If the icon we're using for this notification matches what the Notification
        // specified should show in the badge, then return true.
        return mIsIconLarge && mBadgeIcon == BADGE_ICON_LARGE
                || !mIsIconLarge && mBadgeIcon == BADGE_ICON_SMALL;
    }
}
Loading