package com.android.quickstep.views; import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; import static com.android.launcher3.anim.Interpolators.LINEAR; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.util.FloatProperty; import com.android.launcher3.anim.Interpolators; public class LiveTileOverlay extends Drawable { private static final long ICON_ANIM_DURATION = 120; private static final FloatProperty PROGRESS = new FloatProperty("progress") { @Override public void setValue(LiveTileOverlay liveTileOverlay, float progress) { liveTileOverlay.setIconAnimationProgress(progress); } @Override public Float get(LiveTileOverlay liveTileOverlay) { return liveTileOverlay.mIconAnimationProgress; } }; private final Paint mPaint = new Paint(); private Rect mBoundsRect = new Rect(); private RectF mCurrentRect; private float mCornerRadius; private Drawable mIcon; private Animator mIconAnimator; private boolean mDrawEnabled = true; private float mIconAnimationProgress = 0f; public LiveTileOverlay() { mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); } public void update(RectF currentRect, float cornerRadius) { invalidateSelf(); mCurrentRect = currentRect; mCornerRadius = cornerRadius; mCurrentRect.roundOut(mBoundsRect); setBounds(mBoundsRect); invalidateSelf(); } public void setIcon(Drawable icon) { mIcon = icon; } public void startIconAnimation() { if (mIconAnimator != null) { mIconAnimator.cancel(); } // This animator must match the icon part of {@link TaskView#FOCUS_TRANSITION} animation. mIconAnimator = ObjectAnimator.ofFloat(this, PROGRESS, 1); mIconAnimator.setDuration(ICON_ANIM_DURATION).setInterpolator(LINEAR); mIconAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mIconAnimator = null; } }); mIconAnimator.start(); } public float cancelIconAnimation() { if (mIconAnimator != null) { mIconAnimator.cancel(); } return mIconAnimationProgress; } public void setDrawEnabled(boolean drawEnabled) { if (mDrawEnabled != drawEnabled) { mDrawEnabled = drawEnabled; invalidateSelf(); } } @Override public void draw(Canvas canvas) { if (mCurrentRect != null && mDrawEnabled) { canvas.drawRoundRect(mCurrentRect, mCornerRadius, mCornerRadius, mPaint); if (mIcon != null && mIconAnimationProgress > 0f) { canvas.save(); float scale = Interpolators.clampToProgress(FAST_OUT_SLOW_IN, 0f, 1f).getInterpolation(mIconAnimationProgress); canvas.translate(mCurrentRect.centerX() - mIcon.getBounds().width() / 2 * scale, mCurrentRect.top - mIcon.getBounds().height() / 2 * scale); canvas.scale(scale, scale); mIcon.draw(canvas); canvas.restore(); } } } @Override public void setAlpha(int i) { } @Override public void setColorFilter(ColorFilter colorFilter) { } @Override public int getOpacity() { return PixelFormat.TRANSLUCENT; } private void setIconAnimationProgress(float progress) { mIconAnimationProgress = progress; invalidateSelf(); } }