From a262a9324bec8743636a4c53e51ee2ada98743d2 Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Thu, 30 May 2024 11:13:32 +0530 Subject: [PATCH 01/11] bl3:make it buildable --- animationlib/build.gradle | 19 ++----------------- iconloaderlib/build.gradle | 10 ++-------- .../launcher3/icons/BaseIconFactory.java | 4 ++-- 3 files changed, 6 insertions(+), 27 deletions(-) diff --git a/animationlib/build.gradle b/animationlib/build.gradle index bd5c575e..e209650c 100644 --- a/animationlib/build.gradle +++ b/animationlib/build.gradle @@ -3,10 +3,6 @@ apply plugin: 'kotlin-android' android { namespace = "com.android.app.animation" - testNamespace = "com.android.app.animation.tests" - defaultConfig { - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } sourceSets { main { @@ -19,25 +15,14 @@ android { manifest.srcFile 'tests/AndroidManifest.xml' } } - - lintOptions { - abortOnError false - } - tasks.lint.enabled = false - tasks.withType(JavaCompile) { - options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" - } - kotlinOptions { - jvmTarget = '1.8' - freeCompilerArgs = ["-Xjvm-default=all"] - } } +addFrameworkJar('framework-14.jar') + dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0" implementation "androidx.core:core-animation:1.0.0-alpha02" implementation "androidx.core:core-ktx:1.9.0" - androidTestImplementation libs.robolectric androidTestImplementation "androidx.test.ext:junit:1.1.3" androidTestImplementation "androidx.test:rules:1.4.0" } diff --git a/iconloaderlib/build.gradle b/iconloaderlib/build.gradle index 344ac20b..3df9d0d7 100644 --- a/iconloaderlib/build.gradle +++ b/iconloaderlib/build.gradle @@ -6,18 +6,12 @@ android { namespace = "com.android.launcher3.icons" sourceSets { main { - java.srcDirs = ['src', 'src_full_lib'] + java.srcDirs = ['src'] manifest.srcFile 'AndroidManifest.xml' res.srcDirs = ['res'] } } - lint { - abortOnError false - } - - tasks.withType(JavaCompile) { - options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" - } + addFrameworkJar('framework-14.jar') } dependencies { diff --git a/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java b/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java index 7c112dab..7c86b022 100644 --- a/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java +++ b/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java @@ -365,8 +365,8 @@ public class BaseIconFactory implements AutoCloseable { * Wraps the provided icon in an adaptive icon drawable */ public AdaptiveIconDrawable wrapToAdaptiveIcon(@NonNull Drawable icon) { - if (icon instanceof AdaptiveIconDrawable aid) { - return aid; + if (icon instanceof AdaptiveIconDrawable) { + return (AdaptiveIconDrawable) icon; } else { EmptyWrapper foreground = new EmptyWrapper(); AdaptiveIconDrawable dr = new AdaptiveIconDrawable( -- GitLab From d374ea32693ed355b63f59f2067e8aee76cac410 Mon Sep 17 00:00:00 2001 From: althafvly Date: Thu, 30 May 2024 11:50:25 +0530 Subject: [PATCH 02/11] add gitignore --- animationlib/.gitignore | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 animationlib/.gitignore diff --git a/animationlib/.gitignore b/animationlib/.gitignore new file mode 100644 index 00000000..6213826a --- /dev/null +++ b/animationlib/.gitignore @@ -0,0 +1,13 @@ +*.iml +.project +.classpath +.project.properties +gen/ +bin/ +.idea/ +.gradle/ +local.properties +gradle/ +build/ +gradlew* +.DS_Store -- GitLab From f2fa848b38b07e3d11129ee35531a2ab780d4b82 Mon Sep 17 00:00:00 2001 From: althafvly Date: Thu, 30 May 2024 11:53:25 +0530 Subject: [PATCH 03/11] Use java 17 --- iconloaderlib/build.gradle | 6 ++++++ .../src/com/android/launcher3/icons/BaseIconFactory.java | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/iconloaderlib/build.gradle b/iconloaderlib/build.gradle index 3df9d0d7..d20960b0 100644 --- a/iconloaderlib/build.gradle +++ b/iconloaderlib/build.gradle @@ -11,6 +11,12 @@ android { res.srcDirs = ['res'] } } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + addFrameworkJar('framework-14.jar') } diff --git a/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java b/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java index 7c86b022..7c112dab 100644 --- a/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java +++ b/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java @@ -365,8 +365,8 @@ public class BaseIconFactory implements AutoCloseable { * Wraps the provided icon in an adaptive icon drawable */ public AdaptiveIconDrawable wrapToAdaptiveIcon(@NonNull Drawable icon) { - if (icon instanceof AdaptiveIconDrawable) { - return (AdaptiveIconDrawable) icon; + if (icon instanceof AdaptiveIconDrawable aid) { + return aid; } else { EmptyWrapper foreground = new EmptyWrapper(); AdaptiveIconDrawable dr = new AdaptiveIconDrawable( -- GitLab From c23d567223afca6f4fd75a689e4f2b626efc18af Mon Sep 17 00:00:00 2001 From: althafvly Date: Wed, 24 Jul 2024 12:33:29 +0530 Subject: [PATCH 04/11] make it buildable --- animationlib/build.gradle | 18 ++++++++---------- iconloaderlib/build.gradle | 7 +++---- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/animationlib/build.gradle b/animationlib/build.gradle index e209650c..39ce7a7a 100644 --- a/animationlib/build.gradle +++ b/animationlib/build.gradle @@ -10,19 +10,17 @@ android { res.srcDirs = ['res'] manifest.srcFile 'AndroidManifest.xml' } - androidTest { - java.srcDirs = ["tests/src", "tests/robolectric/src"] - manifest.srcFile 'tests/AndroidManifest.xml' - } } -} -addFrameworkJar('framework-14.jar') + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + + addFrameworkJar('framework-14.jar') +} dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0" - implementation "androidx.core:core-animation:1.0.0-alpha02" + implementation "androidx.core:core-animation:1.0.0" implementation "androidx.core:core-ktx:1.9.0" - androidTestImplementation "androidx.test.ext:junit:1.1.3" - androidTestImplementation "androidx.test:rules:1.4.0" } diff --git a/iconloaderlib/build.gradle b/iconloaderlib/build.gradle index d20960b0..5b4c6320 100644 --- a/iconloaderlib/build.gradle +++ b/iconloaderlib/build.gradle @@ -1,6 +1,5 @@ -plugins { - id 'com.android.library' -} +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' android { namespace = "com.android.launcher3.icons" @@ -21,5 +20,5 @@ android { } dependencies { - implementation "androidx.core:core" + implementation "androidx.core:core-ktx:1.9.0" } -- GitLab From 35d556fcbbafc9146d89ea5200797e9114f3cbbb Mon Sep 17 00:00:00 2001 From: Yash Garg Date: Mon, 27 Mar 2023 21:17:45 +0530 Subject: [PATCH 05/11] feat(dots): notification count support for launcher3 app badges --- .../android/launcher3/icons/DotRenderer.java | 67 +++++++++++++++++-- 1 file changed, 63 insertions(+), 4 deletions(-) diff --git a/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java b/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java index a42232e3..f64688f0 100644 --- a/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java +++ b/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java @@ -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. */ @@ -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; @@ -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; } @@ -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) { @@ -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; @@ -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) @@ -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; + } } -- GitLab From 070ee9dfcc17e6b2163c61af3239def06672ff0a Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Tue, 4 Apr 2023 19:32:07 +0530 Subject: [PATCH 06/11] feat(icons): Add month icon support for calendar --- .../android/launcher3/icons/IconProvider.java | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/iconloaderlib/src/com/android/launcher3/icons/IconProvider.java b/iconloaderlib/src/com/android/launcher3/icons/IconProvider.java index e8ce3b18..2f36d741 100644 --- a/iconloaderlib/src/com/android/launcher3/icons/IconProvider.java +++ b/iconloaderlib/src/com/android/launcher3/icons/IconProvider.java @@ -69,6 +69,8 @@ public class IconProvider { public static final boolean ATLEAST_T = BuildCompat.isAtLeastT(); private static final String ICON_METADATA_KEY_PREFIX = ".dynamic_icons"; + private static final String MONTH_BG_ICON_METADATA_KEY_PREFIX = ".month_dynamic_icons"; + private static final String DAY_FG_ICON_METADATA_KEY_PREFIX = ".day_dynamic_icons"; private static final String SYSTEM_STATE_SEPARATOR = " "; @@ -173,7 +175,9 @@ public class IconProvider { .metaData; final Resources resources = pm.getResourcesForApplication(mCalendar.getPackageName()); final int id = getDynamicIconId(metadata, resources); - if (id != ID_NULL) { + final int[] monthDayIds = getDynamicBackgroundIconId(metadata, resources); + if (id != ID_NULL && (monthDayIds == null || + monthDayIds[0] == ID_NULL || monthDayIds[1] == ID_NULL )) { if (DEBUG) Log.d(TAG, "Got icon #" + id); Drawable drawable = resources.getDrawableForDensity(id, iconDpi, null /* theme */); if (ATLEAST_T && drawable instanceof AdaptiveIconDrawable && td != null) { @@ -191,6 +195,10 @@ public class IconProvider { } } return drawable; + } else if (monthDayIds != null) { + Drawable background = resources.getDrawableForDensity(monthDayIds[0], iconDpi, null /* theme */); + Drawable foreground = resources.getDrawableForDensity(monthDayIds[1], iconDpi, null /* theme */); + return new AdaptiveIconDrawable(background, foreground); } } catch (PackageManager.NameNotFoundException e) { if (DEBUG) { @@ -225,6 +233,28 @@ public class IconProvider { } } + private int[] getDynamicBackgroundIconId(Bundle metadata, Resources resources) { + if (metadata == null) { + return null; + } + String bgKey = mCalendar.getPackageName() + MONTH_BG_ICON_METADATA_KEY_PREFIX; + String fgKey = mCalendar.getPackageName() + DAY_FG_ICON_METADATA_KEY_PREFIX; + final int bgArrayId = metadata.getInt(bgKey, ID_NULL); + final int fgArrayId = metadata.getInt(fgKey, ID_NULL); + if (bgArrayId == ID_NULL || fgArrayId == ID_NULL) { + return null; + } + try { + return new int[] {resources.obtainTypedArray(bgArrayId).getResourceId(getMonth(), ID_NULL), + resources.obtainTypedArray(fgArrayId).getResourceId(getDay(), ID_NULL)}; + } catch (Resources.NotFoundException e) { + if (DEBUG) { + Log.d(TAG, "package defines '" + bgKey + " and " + fgKey + "' but corresponding array not found"); + } + return null; + } + } + /** * @return Today's day of the month, zero-indexed. */ @@ -232,6 +262,10 @@ public class IconProvider { return Calendar.getInstance().get(Calendar.DAY_OF_MONTH) - 1; } + private static int getMonth() { + return Calendar.getInstance().get(Calendar.MONTH); + } + private static ComponentName parseComponentOrNull(Context context, int resId) { String cn = context.getString(resId); return TextUtils.isEmpty(cn) ? null : ComponentName.unflattenFromString(cn); -- GitLab From d5f69c65e9521a067dee6057e3aed9e29a842a7d Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Thu, 13 Apr 2023 18:49:02 +0530 Subject: [PATCH 07/11] iconloader: Add unchanges constructor for aosp --- .../src/com/android/launcher3/icons/DotRenderer.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java b/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java index f64688f0..1f5c49be 100644 --- a/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java +++ b/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java @@ -62,6 +62,10 @@ public class DotRenderer { private final Rect mTextRect = new Rect(); private final boolean mDisplayCount; + public DotRenderer(int iconSizePx, Path iconShapePath, int pathSize) { + this(iconSizePx, iconShapePath, pathSize, false, null); + } + 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); @@ -116,6 +120,10 @@ public class DotRenderer { /** * Draw a circle on top of the canvas according to the given params. */ + public void draw(Canvas canvas, DrawParams params) { + draw(canvas, params, 0); + } + public void draw(Canvas canvas, DrawParams params, int numNotifications) { if (params == null) { Log.e(TAG, "Invalid null argument(s) passed in call to draw."); -- GitLab From e1770b42fe6685088ed25d99734ad86f7c9349e4 Mon Sep 17 00:00:00 2001 From: Yash Garg Date: Sun, 26 Nov 2023 23:03:41 +0530 Subject: [PATCH 08/11] feat: convert badge to round rect when count > 99 --- .../android/launcher3/icons/DotRenderer.java | 36 +++++++++++++++---- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java b/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java index 1f5c49be..0ffcede5 100644 --- a/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java +++ b/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java @@ -45,7 +45,7 @@ public class DotRenderer { 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 static final int MAX_COUNT = 999; private final float mCircleRadius; private final Paint mCirclePaint = new Paint(ANTI_ALIAS_FLAG | FILTER_BITMAP_FLAG); @@ -144,18 +144,34 @@ public class DotRenderer { float offsetY = Math.max(0, canvasBounds.top - (dotCenterY + mBitmapOffset)); // We draw the dot relative to its center. - canvas.translate(dotCenterX + offsetX, dotCenterY + offsetY); + float dx = dotCenterX + offsetX; + float dy = dotCenterY + offsetY - 15f; + + if (numNotifications > 9 && numNotifications < 100) { + canvas.translate(dx - 3f, dy); + } else if (numNotifications > 99 && numNotifications < 1000) { + canvas.translate(dx + 6f, dy); + } else { + canvas.translate(dx - 12f, dy); + } + canvas.scale(params.scale, params.scale); - mCirclePaint.setColor(Color.BLACK); - canvas.drawBitmap(mBackgroundWithShadow, mBitmapOffset, mBitmapOffset, mCirclePaint); mCirclePaint.setColor(params.dotColor); - canvas.drawCircle(0, 0, mCircleRadius, mCirclePaint); + if (numNotifications > 9 && numNotifications < 100) { + canvas.drawRoundRect(new RectF(-mCircleRadius - 10, -mCircleRadius, mCircleRadius + 10, mCircleRadius), 50, 50, mCirclePaint); + } else if (numNotifications > 99 && numNotifications < 1000) { + canvas.drawRoundRect(new RectF(-mCircleRadius - 20, -mCircleRadius, mCircleRadius + 20, mCircleRadius), 50, 50, mCirclePaint); + } else { + 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.setTextSize(42f); + mTextPaint.setTypeface(Typeface.DEFAULT_BOLD); + String text = numToNotation(numNotifications); mTextPaint.getTextBounds(text, 0, text.length(), mTextRect); float x = (-mTextRect.width() / 2f - mTextRect.left) * getAdjustment(numNotifications); float y = mTextRect.height() / 2f - mTextRect.bottom; @@ -165,6 +181,14 @@ public class DotRenderer { canvas.restore(); } + private String numToNotation(int num) { + if (num < 1000) { + return String.valueOf(num); + } else { + return num / 1000 + "k"; + } + } + /** * Returns the color to use for the counter text based on the dot's background color. * -- GitLab From df5276a83a2d8980b12df98143bf2c9bd212cc32 Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Tue, 12 Dec 2023 14:08:26 +0530 Subject: [PATCH 09/11] DotRenderer: Add shadow to notification dots --- .../src/com/android/launcher3/icons/DotRenderer.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java b/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java index 0ffcede5..6de00d42 100644 --- a/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java +++ b/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java @@ -49,6 +49,8 @@ public class DotRenderer { private final float mCircleRadius; private final Paint mCirclePaint = new Paint(ANTI_ALIAS_FLAG | FILTER_BITMAP_FLAG); + private final Paint mCircleShadowPaint = new Paint(ANTI_ALIAS_FLAG | FILTER_BITMAP_FLAG); + private final Paint mTextPaint = new Paint(ANTI_ALIAS_FLAG | FILTER_BITMAP_FLAG); private final Bitmap mBackgroundWithShadow; @@ -158,11 +160,15 @@ public class DotRenderer { canvas.scale(params.scale, params.scale); mCirclePaint.setColor(params.dotColor); + mCircleShadowPaint.setColor(params.shadowDotColor); if (numNotifications > 9 && numNotifications < 100) { + canvas.drawRoundRect(new RectF(-mCircleRadius - 10, -mCircleRadius, mCircleRadius + 10, mCircleRadius + 3), 50, 50, mCircleShadowPaint); canvas.drawRoundRect(new RectF(-mCircleRadius - 10, -mCircleRadius, mCircleRadius + 10, mCircleRadius), 50, 50, mCirclePaint); } else if (numNotifications > 99 && numNotifications < 1000) { + canvas.drawRoundRect(new RectF(-mCircleRadius - 20, -mCircleRadius, mCircleRadius + 20, mCircleRadius + 3), 50, 50, mCircleShadowPaint); canvas.drawRoundRect(new RectF(-mCircleRadius - 20, -mCircleRadius, mCircleRadius + 20, mCircleRadius), 50, 50, mCirclePaint); } else { + canvas.drawCircle(0, 3, mCircleRadius, mCircleShadowPaint); canvas.drawCircle(0, 0, mCircleRadius, mCirclePaint); } @@ -215,6 +221,8 @@ public class DotRenderer { /** 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; + @ViewDebug.ExportedProperty(category = "notification dot", formatToHexString = true) + public int shadowDotColor; } /** -- GitLab From c01e49e69c17168f5abd95ac2911ace34c4ce020 Mon Sep 17 00:00:00 2001 From: althafvly Date: Thu, 29 Feb 2024 21:22:20 +0530 Subject: [PATCH 10/11] feat: adjust dot size accordingly --- .../android/launcher3/icons/DotRenderer.java | 51 +++++++------------ 1 file changed, 17 insertions(+), 34 deletions(-) diff --git a/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java b/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java index 6de00d42..066760de 100644 --- a/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java +++ b/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java @@ -76,7 +76,7 @@ public class DotRenderer { } ShadowGenerator.Builder builder = new ShadowGenerator.Builder(Color.TRANSPARENT); builder.ambientShadowAlpha = 88; - mBackgroundWithShadow = builder.setupBlurForSize(size).createPill(size, size); + mBackgroundWithShadow = builder.setupBlurForSize(size).createPill(size, displayCount ? (size - 25) : size); mCircleRadius = builder.radius; mBitmapOffset = -mBackgroundWithShadow.getHeight() * 0.5f; // Same as width. @@ -161,27 +161,32 @@ public class DotRenderer { mCirclePaint.setColor(params.dotColor); mCircleShadowPaint.setColor(params.shadowDotColor); - if (numNotifications > 9 && numNotifications < 100) { - canvas.drawRoundRect(new RectF(-mCircleRadius - 10, -mCircleRadius, mCircleRadius + 10, mCircleRadius + 3), 50, 50, mCircleShadowPaint); - canvas.drawRoundRect(new RectF(-mCircleRadius - 10, -mCircleRadius, mCircleRadius + 10, mCircleRadius), 50, 50, mCirclePaint); - } else if (numNotifications > 99 && numNotifications < 1000) { - canvas.drawRoundRect(new RectF(-mCircleRadius - 20, -mCircleRadius, mCircleRadius + 20, mCircleRadius + 3), 50, 50, mCircleShadowPaint); - canvas.drawRoundRect(new RectF(-mCircleRadius - 20, -mCircleRadius, mCircleRadius + 20, mCircleRadius), 50, 50, mCirclePaint); + + if (numNotifications >= 10 && numNotifications < 1000) { + canvas.drawRoundRect(new RectF(-mCircleRadius + 10, -mCircleRadius, mCircleRadius + 20, mCircleRadius), 50, 50, mCircleShadowPaint); + canvas.drawRoundRect(new RectF(-mCircleRadius + 10, -mCircleRadius, mCircleRadius + 20, mCircleRadius), 50, 50, mCirclePaint); } else { - canvas.drawCircle(0, 3, mCircleRadius, mCircleShadowPaint); - canvas.drawCircle(0, 0, mCircleRadius, mCirclePaint); + canvas.drawCircle(5, 10, mCircleRadius, mCircleShadowPaint); + canvas.drawCircle(5, 10, mCircleRadius, mCirclePaint); } if (mDisplayCount && numNotifications > 0) { // Draw the numNotifications text mTextPaint.setColor(getCounterTextColor(Color.WHITE)); - mTextPaint.setTextSize(42f); mTextPaint.setTypeface(Typeface.DEFAULT_BOLD); + mTextPaint.setTextSize(32f); String text = numToNotation(numNotifications); 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); + if (numNotifications < 10) { + canvas.drawText(text, -4f, 22f, mTextPaint); + } else if (numNotifications < 100) { + canvas.drawText(text, -4f, y, mTextPaint); + } else if (numNotifications >= 1000) { + canvas.drawText(text, -14f, 20f, mTextPaint); + } else { + canvas.drawText(text, -14f, y, mTextPaint); + } } canvas.restore(); @@ -224,26 +229,4 @@ public class DotRenderer { @ViewDebug.ExportedProperty(category = "notification dot", formatToHexString = true) public int shadowDotColor; } - - /** - * 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; - } } -- GitLab From 82de263300bedf3a5e4ba4552dd65347c267bd81 Mon Sep 17 00:00:00 2001 From: althafvly Date: Tue, 16 Apr 2024 10:06:22 +0530 Subject: [PATCH 11/11] feat: adjust position of dots and add checks feat: Don't draw empty notification dot --- .../com/android/launcher3/icons/DotRenderer.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java b/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java index 066760de..94f0402b 100644 --- a/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java +++ b/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java @@ -149,11 +149,9 @@ public class DotRenderer { float dx = dotCenterX + offsetX; float dy = dotCenterY + offsetY - 15f; - if (numNotifications > 9 && numNotifications < 100) { - canvas.translate(dx - 3f, dy); - } else if (numNotifications > 99 && numNotifications < 1000) { - canvas.translate(dx + 6f, dy); - } else { + if (numNotifications > 9 && numNotifications < 1000) { + canvas.translate(dx - 17f, dy); + } else if (numNotifications > 0) { canvas.translate(dx - 12f, dy); } @@ -165,7 +163,7 @@ public class DotRenderer { if (numNotifications >= 10 && numNotifications < 1000) { canvas.drawRoundRect(new RectF(-mCircleRadius + 10, -mCircleRadius, mCircleRadius + 20, mCircleRadius), 50, 50, mCircleShadowPaint); canvas.drawRoundRect(new RectF(-mCircleRadius + 10, -mCircleRadius, mCircleRadius + 20, mCircleRadius), 50, 50, mCirclePaint); - } else { + } else if (numNotifications > 0) { canvas.drawCircle(5, 10, mCircleRadius, mCircleShadowPaint); canvas.drawCircle(5, 10, mCircleRadius, mCirclePaint); } @@ -181,11 +179,11 @@ public class DotRenderer { if (numNotifications < 10) { canvas.drawText(text, -4f, 22f, mTextPaint); } else if (numNotifications < 100) { - canvas.drawText(text, -4f, y, mTextPaint); + canvas.drawText(text, -3f, y, mTextPaint); } else if (numNotifications >= 1000) { canvas.drawText(text, -14f, 20f, mTextPaint); } else { - canvas.drawText(text, -14f, y, mTextPaint); + canvas.drawText(text, -12f, y, mTextPaint); } } -- GitLab