Loading iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java +63 −4 Original line number Diff line number Diff line Loading @@ -27,9 +27,12 @@ import android.graphics.Path; import android.graphics.PathMeasure; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Typeface; import android.util.Log; import android.view.ViewDebug; import androidx.core.graphics.ColorUtils; /** * Used to draw a notification dot on top of an icon. */ Loading @@ -38,10 +41,15 @@ public class DotRenderer { private static final String TAG = "DotRenderer"; // The dot size is defined as a percentage of the app icon size. private static final float SIZE_PERCENTAGE = 0.228f; private static final float SIZE_PERCENTAGE = 0.21f; private static final float SIZE_PERCENTAGE_WITH_COUNT = 0.28f; // The max number to draw on dots private static final int MAX_COUNT = 99; private final float mCircleRadius; private final Paint mCirclePaint = new Paint(ANTI_ALIAS_FLAG | FILTER_BITMAP_FLAG); private final Paint mTextPaint = new Paint(ANTI_ALIAS_FLAG | FILTER_BITMAP_FLAG); private final Bitmap mBackgroundWithShadow; private final float mBitmapOffset; Loading @@ -51,8 +59,12 @@ public class DotRenderer { private final float[] mLeftDotPosition; private static final int MIN_DOT_SIZE = 1; public DotRenderer(int iconSizePx, Path iconShapePath, int pathSize) { int size = Math.round(SIZE_PERCENTAGE * iconSizePx); private final Rect mTextRect = new Rect(); private final boolean mDisplayCount; public DotRenderer(int iconSizePx, Path iconShapePath, int pathSize, Boolean displayCount, Typeface typeface) { mDisplayCount = displayCount; int size = Math.round((displayCount ? SIZE_PERCENTAGE_WITH_COUNT : SIZE_PERCENTAGE) * iconSizePx); if (size <= 0) { size = MIN_DOT_SIZE; } Loading @@ -66,6 +78,10 @@ public class DotRenderer { // Find the points on the path that are closest to the top left and right corners. mLeftDotPosition = getPathPoint(iconShapePath, pathSize, -1); mRightDotPosition = getPathPoint(iconShapePath, pathSize, 1); mTextPaint.setTextSize(size * 0.65f); mTextPaint.setTextAlign(Paint.Align.LEFT); mTextPaint.setTypeface(typeface); } private static float[] getPathPoint(Path path, float size, float direction) { Loading Loading @@ -100,7 +116,7 @@ public class DotRenderer { /** * Draw a circle on top of the canvas according to the given params. */ public void draw(Canvas canvas, DrawParams params) { public void draw(Canvas canvas, DrawParams params, int numNotifications) { if (params == null) { Log.e(TAG, "Invalid null argument(s) passed in call to draw."); return; Loading @@ -127,9 +143,30 @@ public class DotRenderer { canvas.drawBitmap(mBackgroundWithShadow, mBitmapOffset, mBitmapOffset, mCirclePaint); mCirclePaint.setColor(params.dotColor); canvas.drawCircle(0, 0, mCircleRadius, mCirclePaint); if (mDisplayCount && numNotifications > 0) { // Draw the numNotifications text mTextPaint.setColor(getCounterTextColor(Color.WHITE)); String text = String.valueOf(Math.min(numNotifications, MAX_COUNT)); mTextPaint.getTextBounds(text, 0, text.length(), mTextRect); float x = (-mTextRect.width() / 2f - mTextRect.left) * getAdjustment(numNotifications); float y = mTextRect.height() / 2f - mTextRect.bottom; canvas.drawText(text, x, y, mTextPaint); } canvas.restore(); } /** * Returns the color to use for the counter text based on the dot's background color. * * @param dotBackgroundColor The color of the dot background. * @return The color to use on the counter text. */ private int getCounterTextColor(int dotBackgroundColor) { return ColorUtils.setAlphaComponent(dotBackgroundColor, 0xFF); } public static class DrawParams { /** The color (possibly based on the icon) to use for the dot. */ @ViewDebug.ExportedProperty(category = "notification dot", formatToHexString = true) Loading @@ -147,4 +184,26 @@ public class DotRenderer { @ViewDebug.ExportedProperty(category = "notification dot") public boolean leftAlign; } /** * An attempt to adjust digits to their perceived center, they were tuned with Roboto but should * (hopefully) work with other OEM fonts as well. */ private float getAdjustment(int number) { switch (number) { case 1: return 1.01f; case 2: return 0.99f; case 3: case 4: case 6: return 0.98f; case 7: return 1.02f; case 9: return 0.9f; } return 1f; } } Loading
iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java +63 −4 Original line number Diff line number Diff line Loading @@ -27,9 +27,12 @@ import android.graphics.Path; import android.graphics.PathMeasure; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Typeface; import android.util.Log; import android.view.ViewDebug; import androidx.core.graphics.ColorUtils; /** * Used to draw a notification dot on top of an icon. */ Loading @@ -38,10 +41,15 @@ public class DotRenderer { private static final String TAG = "DotRenderer"; // The dot size is defined as a percentage of the app icon size. private static final float SIZE_PERCENTAGE = 0.228f; private static final float SIZE_PERCENTAGE = 0.21f; private static final float SIZE_PERCENTAGE_WITH_COUNT = 0.28f; // The max number to draw on dots private static final int MAX_COUNT = 99; private final float mCircleRadius; private final Paint mCirclePaint = new Paint(ANTI_ALIAS_FLAG | FILTER_BITMAP_FLAG); private final Paint mTextPaint = new Paint(ANTI_ALIAS_FLAG | FILTER_BITMAP_FLAG); private final Bitmap mBackgroundWithShadow; private final float mBitmapOffset; Loading @@ -51,8 +59,12 @@ public class DotRenderer { private final float[] mLeftDotPosition; private static final int MIN_DOT_SIZE = 1; public DotRenderer(int iconSizePx, Path iconShapePath, int pathSize) { int size = Math.round(SIZE_PERCENTAGE * iconSizePx); private final Rect mTextRect = new Rect(); private final boolean mDisplayCount; public DotRenderer(int iconSizePx, Path iconShapePath, int pathSize, Boolean displayCount, Typeface typeface) { mDisplayCount = displayCount; int size = Math.round((displayCount ? SIZE_PERCENTAGE_WITH_COUNT : SIZE_PERCENTAGE) * iconSizePx); if (size <= 0) { size = MIN_DOT_SIZE; } Loading @@ -66,6 +78,10 @@ public class DotRenderer { // Find the points on the path that are closest to the top left and right corners. mLeftDotPosition = getPathPoint(iconShapePath, pathSize, -1); mRightDotPosition = getPathPoint(iconShapePath, pathSize, 1); mTextPaint.setTextSize(size * 0.65f); mTextPaint.setTextAlign(Paint.Align.LEFT); mTextPaint.setTypeface(typeface); } private static float[] getPathPoint(Path path, float size, float direction) { Loading Loading @@ -100,7 +116,7 @@ public class DotRenderer { /** * Draw a circle on top of the canvas according to the given params. */ public void draw(Canvas canvas, DrawParams params) { public void draw(Canvas canvas, DrawParams params, int numNotifications) { if (params == null) { Log.e(TAG, "Invalid null argument(s) passed in call to draw."); return; Loading @@ -127,9 +143,30 @@ public class DotRenderer { canvas.drawBitmap(mBackgroundWithShadow, mBitmapOffset, mBitmapOffset, mCirclePaint); mCirclePaint.setColor(params.dotColor); canvas.drawCircle(0, 0, mCircleRadius, mCirclePaint); if (mDisplayCount && numNotifications > 0) { // Draw the numNotifications text mTextPaint.setColor(getCounterTextColor(Color.WHITE)); String text = String.valueOf(Math.min(numNotifications, MAX_COUNT)); mTextPaint.getTextBounds(text, 0, text.length(), mTextRect); float x = (-mTextRect.width() / 2f - mTextRect.left) * getAdjustment(numNotifications); float y = mTextRect.height() / 2f - mTextRect.bottom; canvas.drawText(text, x, y, mTextPaint); } canvas.restore(); } /** * Returns the color to use for the counter text based on the dot's background color. * * @param dotBackgroundColor The color of the dot background. * @return The color to use on the counter text. */ private int getCounterTextColor(int dotBackgroundColor) { return ColorUtils.setAlphaComponent(dotBackgroundColor, 0xFF); } public static class DrawParams { /** The color (possibly based on the icon) to use for the dot. */ @ViewDebug.ExportedProperty(category = "notification dot", formatToHexString = true) Loading @@ -147,4 +184,26 @@ public class DotRenderer { @ViewDebug.ExportedProperty(category = "notification dot") public boolean leftAlign; } /** * An attempt to adjust digits to their perceived center, they were tuned with Roboto but should * (hopefully) work with other OEM fonts as well. */ private float getAdjustment(int number) { switch (number) { case 1: return 1.01f; case 2: return 0.99f; case 3: case 4: case 6: return 0.98f; case 7: return 1.02f; case 9: return 0.9f; } return 1f; } }