diff options
4 files changed, 59 insertions, 34 deletions
diff --git a/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java b/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java index 6bc859aa6..af07aa3a9 100644 --- a/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java +++ b/iconloaderlib/src/com/android/launcher3/icons/DotRenderer.java @@ -23,8 +23,10 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; -import android.graphics.Point; +import android.graphics.Path; +import android.graphics.PathMeasure; import android.graphics.Rect; +import android.graphics.RectF; import android.util.Log; import android.view.ViewDebug; @@ -36,33 +38,51 @@ 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.38f; + private static final float SIZE_PERCENTAGE = 0.228f; - // Extra scale down of the dot - private static final float DOT_SCALE = 0.6f; - - // Offset the dot slightly away from the icon if there's space. - private static final float OFFSET_PERCENTAGE = 0.02f; - - private final float mDotCenterOffset; - private final int mOffset; private final float mCircleRadius; private final Paint mCirclePaint = new Paint(ANTI_ALIAS_FLAG | FILTER_BITMAP_FLAG); private final Bitmap mBackgroundWithShadow; private final float mBitmapOffset; - public DotRenderer(int iconSizePx) { - mDotCenterOffset = SIZE_PERCENTAGE * iconSizePx; - mOffset = (int) (OFFSET_PERCENTAGE * iconSizePx); + // Stores the center x and y position as a percentage (0 to 1) of the icon size + private final float[] mRightDotPosition; + private final float[] mLeftDotPosition; - int size = (int) (DOT_SCALE * mDotCenterOffset); + public DotRenderer(int iconSizePx, Path iconShapePath, int pathSize) { + int size = Math.round(SIZE_PERCENTAGE * iconSizePx); ShadowGenerator.Builder builder = new ShadowGenerator.Builder(Color.TRANSPARENT); builder.ambientShadowAlpha = 88; mBackgroundWithShadow = builder.setupBlurForSize(size).createPill(size, size); mCircleRadius = builder.radius; mBitmapOffset = -mBackgroundWithShadow.getHeight() * 0.5f; // Same as width. + + // 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); + } + + private static float[] getPathPoint(Path path, float size, float direction) { + float halfSize = size / 2; + // Small delta so that we don't get a zero size triangle + float delta = 1; + + float x = halfSize + direction * halfSize; + Path trianglePath = new Path(); + trianglePath.moveTo(halfSize, halfSize); + trianglePath.lineTo(x + delta * direction, 0); + trianglePath.lineTo(x, -delta); + trianglePath.close(); + + trianglePath.op(path, Path.Op.INTERSECT); + float[] pos = new float[2]; + new PathMeasure(trianglePath, false).getPosTan(0, pos, null); + + pos[0] = pos[0] / size; + pos[1] = pos[1] / size; + return pos; } /** @@ -74,15 +94,21 @@ public class DotRenderer { return; } canvas.save(); + + Rect iconBounds = params.iconBounds; + float[] dotPosition = params.leftAlign ? mLeftDotPosition : mRightDotPosition; + float dotCenterX = iconBounds.left + iconBounds.width() * dotPosition[0]; + float dotCenterY = iconBounds.top + iconBounds.height() * dotPosition[1]; + + // Ensure dot fits entirely in canvas clip bounds. + Rect canvasBounds = canvas.getClipBounds(); + float offsetX = params.leftAlign + ? Math.max(0, canvasBounds.left - (dotCenterX + mBitmapOffset)) + : Math.min(0, canvasBounds.right - (dotCenterX - mBitmapOffset)); + float offsetY = Math.max(0, canvasBounds.top - (dotCenterY + mBitmapOffset)); + // 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, params.spaceForOffset.x); - int offsetY = Math.min(mOffset, params.spaceForOffset.y); - canvas.translate(dotCenterX + offsetX, dotCenterY - offsetY); + canvas.translate(dotCenterX + offsetX, dotCenterY + offsetY); canvas.scale(params.scale, params.scale); mCirclePaint.setColor(Color.BLACK); @@ -102,9 +128,6 @@ public class DotRenderer { /** 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; diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index 8291acc59..bff7f4213 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -46,10 +46,12 @@ import com.android.launcher3.dot.DotInfo; import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.graphics.DrawableFactory; import com.android.launcher3.graphics.IconPalette; +import com.android.launcher3.graphics.IconShape; 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.icons.LauncherIcons; import com.android.launcher3.model.PackageItemInfo; import com.android.launcher3.views.ActivityContext; @@ -388,7 +390,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, protected void drawDotIfNecessary(Canvas canvas) { if (!mForceHideDot && (hasDot() || mDotParams.scale > 0)) { getIconBounds(mDotParams.iconBounds); - mDotParams.spaceForOffset.set((getWidth() - mIconSize) / 2, getPaddingTop()); + Utilities.scaleRectAboutCenter(mDotParams.iconBounds, IconShape.getNormalizationScale()); final int scrollX = getScrollX(); final int scrollY = getScrollY(); canvas.translate(scrollX, scrollY); diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index c0affb944..3d2d7cf9e 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -24,15 +24,13 @@ import android.graphics.PointF; import android.graphics.Rect; import android.util.DisplayMetrics; import android.view.Surface; -import android.view.View; import android.view.WindowManager; import com.android.launcher3.CellLayout.ContainerType; +import com.android.launcher3.graphics.IconShape; import com.android.launcher3.icons.DotRenderer; import com.android.launcher3.icons.IconNormalizer; -import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT; - public class DeviceProfile { public final InvariantDeviceProfile inv; @@ -240,7 +238,8 @@ public class DeviceProfile { updateWorkspacePadding(); // This is done last, after iconSizePx is calculated above. - mDotRenderer = new DotRenderer(iconSizePx); + mDotRenderer = new DotRenderer(iconSizePx, IconShape.getShapePath(), + IconShape.DEFAULT_PATH_SIZE); } public DeviceProfile copy(Context context) { diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java index 6fa9ba9ae..8d9c52065 100644 --- a/src/com/android/launcher3/folder/FolderIcon.java +++ b/src/com/android/launcher3/folder/FolderIcon.java @@ -36,6 +36,8 @@ import android.view.ViewDebug; import android.view.ViewGroup; import android.widget.FrameLayout; +import androidx.annotation.NonNull; + import com.android.launcher3.Alarm; import com.android.launcher3.AppInfo; import com.android.launcher3.BubbleTextView; @@ -50,11 +52,11 @@ import com.android.launcher3.Launcher; import com.android.launcher3.LauncherSettings; import com.android.launcher3.OnAlarmListener; import com.android.launcher3.R; -import com.android.launcher3.WorkspaceItemInfo; import com.android.launcher3.SimpleOnStylusPressListener; import com.android.launcher3.StylusEventHelper; import com.android.launcher3.Utilities; import com.android.launcher3.Workspace; +import com.android.launcher3.WorkspaceItemInfo; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.dot.FolderDotInfo; import com.android.launcher3.dragndrop.BaseItemDragListener; @@ -68,8 +70,6 @@ import com.android.launcher3.widget.PendingAddShortcutInfo; import java.util.ArrayList; import java.util.List; -import androidx.annotation.NonNull; - /** * An icon that can appear on in the workspace representing an {@link Folder}. */ @@ -510,10 +510,11 @@ public class FolderIcon extends FrameLayout implements FolderListener { Rect iconBounds = mDotParams.iconBounds; BubbleTextView.getIconBounds(this, iconBounds, mLauncher.getWallpaperDeviceProfile().iconSizePx); + float iconScale = (float) mBackground.previewSize / iconBounds.width(); + Utilities.scaleRectAboutCenter(iconBounds, iconScale); // If we are animating to the accepting state, animate the dot out. mDotParams.scale = Math.max(0, mDotScale - mBackground.getScaleProgress()); - mDotParams.spaceForOffset.set(getWidth() - iconBounds.right, iconBounds.top); mDotParams.color = mBackground.getDotColor(); mDotRenderer.draw(canvas, mDotParams); } |