1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.launcher3.badge; 18 19 import static android.graphics.Paint.ANTI_ALIAS_FLAG; 20 import static android.graphics.Paint.FILTER_BITMAP_FLAG; 21 22 import android.graphics.Bitmap; 23 import android.graphics.Canvas; 24 import android.graphics.Color; 25 import android.graphics.Paint; 26 import android.graphics.Point; 27 import android.graphics.Rect; 28 import android.util.Log; 29 30 import com.android.launcher3.graphics.ShadowGenerator; 31 32 /** 33 * Contains parameters necessary to draw a badge for an icon (e.g. the size of the badge). 34 * @see BadgeInfo for the data to draw 35 */ 36 public class BadgeRenderer { 37 38 private static final String TAG = "BadgeRenderer"; 39 40 // The badge sizes are defined as percentages of the app icon size. 41 private static final float SIZE_PERCENTAGE = 0.38f; 42 43 // Extra scale down of the dot 44 private static final float DOT_SCALE = 0.6f; 45 46 // Used to expand the width of the badge for each additional digit. 47 private static final float OFFSET_PERCENTAGE = 0.02f; 48 49 private final float mDotCenterOffset; 50 private final int mOffset; 51 private final float mCircleRadius; 52 private final Paint mCirclePaint = new Paint(ANTI_ALIAS_FLAG | FILTER_BITMAP_FLAG); 53 54 private final Bitmap mBackgroundWithShadow; 55 private final float mBitmapOffset; 56 57 public BadgeRenderer(int iconSizePx) { 58 mDotCenterOffset = SIZE_PERCENTAGE * iconSizePx; 59 mOffset = (int) (OFFSET_PERCENTAGE * iconSizePx); 60 61 int size = (int) (DOT_SCALE * mDotCenterOffset); 62 ShadowGenerator.Builder builder = new ShadowGenerator.Builder(Color.TRANSPARENT); 63 mBackgroundWithShadow = builder.setupBlurForSize(size).createPill(size, size); 64 mCircleRadius = builder.radius; 65 66 mBitmapOffset = -mBackgroundWithShadow.getHeight() * 0.5f; // Same as width. 67 } 68 69 /** 70 * Draw a circle in the top right corner of the given bounds, and draw 71 * {@link BadgeInfo#getNotificationCount()} on top of the circle. 72 * @param color The color (based on the icon) to use for the badge. 73 * @param iconBounds The bounds of the icon being badged. 74 * @param badgeScale The progress of the animation, from 0 to 1. 75 * @param spaceForOffset How much space is available to offset the badge up and to the right. 76 */ 77 public void draw( 78 Canvas canvas, int color, Rect iconBounds, float badgeScale, Point spaceForOffset) { 79 if (iconBounds == null || spaceForOffset == null) { 80 Log.e(TAG, "Invalid null argument(s) passed in call to draw."); 81 return; 82 } 83 canvas.save(); 84 // We draw the badge relative to its center. 85 float badgeCenterX = iconBounds.right - mDotCenterOffset / 2; 86 float badgeCenterY = iconBounds.top + mDotCenterOffset / 2; 87 88 int offsetX = Math.min(mOffset, spaceForOffset.x); 89 int offsetY = Math.min(mOffset, spaceForOffset.y); 90 canvas.translate(badgeCenterX + offsetX, badgeCenterY - offsetY); 91 canvas.scale(badgeScale, badgeScale); 92 93 mCirclePaint.setColor(Color.BLACK); 94 canvas.drawBitmap(mBackgroundWithShadow, mBitmapOffset, mBitmapOffset, mCirclePaint); 95 mCirclePaint.setColor(color); 96 canvas.drawCircle(0, 0, mCircleRadius, mCirclePaint); 97 canvas.restore(); 98 } 99 } 100