diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index 19a3002665..a296f46ef4 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -380,6 +380,28 @@ public final class Utilities { outPivot.y = dst.top + dst.height() * pivotYPct; } + /** + * Scales a {@code RectF} in place about a specified pivot point. + * + *

This method modifies the given {@code RectF} directly to scale it proportionally + * by the given {@code scale}, while preserving its center at the specified + * {@code (pivotX, pivotY)} coordinates. + * + * @param rectF the {@code RectF} to scale, modified directly. + * @param pivotX the x-coordinate of the pivot point about which to scale. + * @param pivotY the y-coordinate of the pivot point about which to scale. + * @param scale the factor by which to scale the rectangle. Values less than 1 will + * shrink the rectangle, while values greater than 1 will enlarge it. + */ + public static void scaleRectFAboutPivot(RectF rectF, float pivotX, float pivotY, float scale) { + rectF.offset(-pivotX, -pivotY); + rectF.left *= scale; + rectF.top *= scale; + rectF.right *= scale; + rectF.bottom *= scale; + rectF.offset(pivotX, pivotY); + } + /** * Maps t from one range to another range. * @param t The value to map. diff --git a/src/com/android/launcher3/apppairs/AppPairIcon.java b/src/com/android/launcher3/apppairs/AppPairIcon.java index 32445ecddb..870c8769ca 100644 --- a/src/com/android/launcher3/apppairs/AppPairIcon.java +++ b/src/com/android/launcher3/apppairs/AppPairIcon.java @@ -18,10 +18,12 @@ package com.android.launcher3.apppairs; import static com.android.launcher3.BubbleTextView.DISPLAY_FOLDER; +import android.animation.ObjectAnimator; import android.content.Context; import android.graphics.Paint; import android.graphics.Rect; import android.util.AttributeSet; +import android.util.FloatProperty; import android.view.LayoutInflater; import android.view.ViewGroup; import android.widget.FrameLayout; @@ -54,6 +56,26 @@ import java.util.function.Predicate; public class AppPairIcon extends FrameLayout implements DraggableView, Reorderable { private static final String TAG = "AppPairIcon"; + // The duration of the scaling animation on hover enter/exit. + private static final int HOVER_SCALE_DURATION = 150; + // The default scale of the icon when not hovered. + private static final Float HOVER_SCALE_DEFAULT = 1f; + // The max scale of the icon when hovered. + private static final Float HOVER_SCALE_MAX = 1.1f; + // Animates the scale of the icon background on hover. + private static final FloatProperty HOVER_SCALE_PROPERTY = + new FloatProperty<>("hoverScale") { + @Override + public void setValue(AppPairIcon view, float scale) { + view.mIconGraphic.setHoverScale(scale); + } + + @Override + public Float get(AppPairIcon view) { + return view.mIconGraphic.getHoverScale(); + } + }; + // A view that holds the app pair icon graphic. private AppPairIconGraphic mIconGraphic; // A view that holds the app pair's title. @@ -250,4 +272,14 @@ public class AppPairIcon extends FrameLayout implements DraggableView, Reorderab } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } + + @Override + public void onHoverChanged(boolean hovered) { + super.onHoverChanged(hovered); + ObjectAnimator + .ofFloat(this, HOVER_SCALE_PROPERTY, + hovered ? HOVER_SCALE_MAX : HOVER_SCALE_DEFAULT) + .setDuration(HOVER_SCALE_DURATION) + .start(); + } } diff --git a/src/com/android/launcher3/apppairs/AppPairIconDrawable.java b/src/com/android/launcher3/apppairs/AppPairIconDrawable.java index db83d91a4b..114ed2edd5 100644 --- a/src/com/android/launcher3/apppairs/AppPairIconDrawable.java +++ b/src/com/android/launcher3/apppairs/AppPairIconDrawable.java @@ -26,6 +26,7 @@ import android.os.Build; import androidx.annotation.NonNull; +import com.android.launcher3.Utilities; import com.android.launcher3.icons.FastBitmapDrawable; /** @@ -128,6 +129,18 @@ public class AppPairIconDrawable extends Drawable { height - (mP.getStandardIconPadding() + mP.getOuterPadding()) ); + // Scale each background from its center edge closest to the center channel. + Utilities.scaleRectFAboutPivot( + leftSide, + leftSide.left + leftSide.width(), + leftSide.top + leftSide.centerY(), + mP.getHoverScale()); + Utilities.scaleRectFAboutPivot( + rightSide, + rightSide.left, + rightSide.top + rightSide.centerY(), + mP.getHoverScale()); + drawCustomRoundedRect(canvas, leftSide, new float[]{ mP.getBigRadius(), mP.getBigRadius(), mP.getSmallRadius(), mP.getSmallRadius(), @@ -163,6 +176,18 @@ public class AppPairIconDrawable extends Drawable { height - (mP.getStandardIconPadding() + mP.getOuterPadding()) ); + // Scale each background from its center edge closest to the center channel. + Utilities.scaleRectFAboutPivot( + topSide, + topSide.left + topSide.centerX(), + topSide.top + topSide.height(), + mP.getHoverScale()); + Utilities.scaleRectFAboutPivot( + bottomSide, + bottomSide.left + bottomSide.centerX(), + bottomSide.top, + mP.getHoverScale()); + drawCustomRoundedRect(canvas, topSide, new float[]{ mP.getBigRadius(), mP.getBigRadius(), mP.getBigRadius(), mP.getBigRadius(), diff --git a/src/com/android/launcher3/apppairs/AppPairIconDrawingParams.kt b/src/com/android/launcher3/apppairs/AppPairIconDrawingParams.kt index 45dc013348..5b546d69de 100644 --- a/src/com/android/launcher3/apppairs/AppPairIconDrawingParams.kt +++ b/src/com/android/launcher3/apppairs/AppPairIconDrawingParams.kt @@ -64,6 +64,8 @@ class AppPairIconDrawingParams(val context: Context, container: Int) { var isLeftRightSplit: Boolean = true // The background paint color (based on container). var bgColor: Int = 0 + // The scale of the icon background while hovered. + var hoverScale: Float = 1f init { val activity: ActivityContext = ActivityContext.lookupContext(context) diff --git a/src/com/android/launcher3/apppairs/AppPairIconGraphic.kt b/src/com/android/launcher3/apppairs/AppPairIconGraphic.kt index dce97eb594..034b686828 100644 --- a/src/com/android/launcher3/apppairs/AppPairIconGraphic.kt +++ b/src/com/android/launcher3/apppairs/AppPairIconGraphic.kt @@ -139,4 +139,19 @@ constructor(context: Context, attrs: AttributeSet? = null) : super.dispatchDraw(canvas) drawable.draw(canvas) } + + /** + * Sets the scale of the icon background while hovered. + */ + fun setHoverScale(scale: Float) { + drawParams.hoverScale = scale + redraw() + } + + /** + * Gets the scale of the icon background while hovered. + */ + fun getHoverScale(): Float { + return drawParams.hoverScale + } }