summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3/PreloadIconDrawable.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/launcher3/PreloadIconDrawable.java')
-rw-r--r--src/com/android/launcher3/PreloadIconDrawable.java168
1 files changed, 168 insertions, 0 deletions
diff --git a/src/com/android/launcher3/PreloadIconDrawable.java b/src/com/android/launcher3/PreloadIconDrawable.java
new file mode 100644
index 000000000..d9365cc1f
--- /dev/null
+++ b/src/com/android/launcher3/PreloadIconDrawable.java
@@ -0,0 +1,168 @@
+package com.android.launcher3;
+
+import android.animation.ObjectAnimator;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
+
+class PreloadIconDrawable extends Drawable {
+ private static final float ANIMATION_PROGRESS_STOPPED = -1.0f;
+ private static final float ANIMATION_PROGRESS_STARTED = 0f;
+ private static final float ANIMATION_PROGRESS_COMPLETED = 1.0f;
+
+ private static final float ICON_SCALE_FACTOR = 0.6f;
+
+ private static Bitmap sProgressBg, sProgressFill;
+
+ private final Rect mCanvasClipRect = new Rect();
+ private final RectF mRect = new RectF();
+ private final Path mProgressPath = new Path();
+ private final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
+
+ final Drawable mIcon;
+
+ /**
+ * Indicates the progress of the preloader [0-100]. If it goes above 100, only the icon
+ * is shown with no progress bar.
+ */
+ private int mProgress = 0;
+ private boolean mPathChanged;
+
+ private float mAnimationProgress = ANIMATION_PROGRESS_STOPPED;
+ private ObjectAnimator mAnimator;
+
+ public PreloadIconDrawable(Drawable icon, Resources res) {
+ mIcon = icon;
+
+ setBounds(icon.getBounds());
+ mPathChanged = false;
+
+ if (sProgressBg == null) {
+ sProgressBg = BitmapFactory.decodeResource(res, R.drawable.bg_preloader);
+ }
+ if (sProgressFill == null) {
+ sProgressFill = BitmapFactory.decodeResource(res, R.drawable.bg_preloader_progress);
+ }
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ final Rect r = getBounds();
+ if (canvas.getClipBounds(mCanvasClipRect) && !Rect.intersects(mCanvasClipRect, r)) {
+ // The draw region has been clipped.
+ return;
+ }
+ final float iconScale;
+
+ if ((mAnimationProgress >= ANIMATION_PROGRESS_STARTED)
+ && (mAnimationProgress < ANIMATION_PROGRESS_COMPLETED)) {
+ mPaint.setAlpha((int) ((1 - mAnimationProgress) * 255));
+ canvas.drawBitmap(sProgressBg, null, r, mPaint);
+ canvas.drawBitmap(sProgressFill, null, r, mPaint);
+ iconScale = ICON_SCALE_FACTOR + (1 - ICON_SCALE_FACTOR) * mAnimationProgress;
+
+ } else if (mAnimationProgress == ANIMATION_PROGRESS_STOPPED) {
+ mPaint.setAlpha(255);
+ iconScale = ICON_SCALE_FACTOR;
+ canvas.drawBitmap(sProgressBg, null, r, mPaint);
+
+ if (mProgress >= 100) {
+ canvas.drawBitmap(sProgressFill, null, r, mPaint);
+ } else if (mProgress > 0) {
+ if (mPathChanged) {
+ mProgressPath.reset();
+ mProgressPath.moveTo(r.exactCenterX(), r.centerY());
+
+ mRect.set(r);
+ mProgressPath.arcTo(mRect, -90, mProgress * 3.6f);
+ mProgressPath.close();
+ mPathChanged = false;
+ }
+
+ canvas.save();
+ canvas.clipPath(mProgressPath);
+ canvas.drawBitmap(sProgressFill, null, r, mPaint);
+ canvas.restore();
+ }
+ } else {
+ iconScale = 1;
+ }
+
+ canvas.save();
+ canvas.scale(iconScale, iconScale, r.exactCenterX(), r.exactCenterY());
+ mIcon.draw(canvas);
+ canvas.restore();
+ }
+
+ @Override
+ protected void onBoundsChange(Rect bounds) {
+ mIcon.setBounds(bounds);
+ mPathChanged = true;
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ mIcon.setAlpha(alpha);
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter cf) {
+ mIcon.setColorFilter(cf);
+ }
+
+ @Override
+ protected boolean onLevelChange(int level) {
+ mProgress = level;
+ mPathChanged = true;
+
+ // Stop Animation
+ if (mAnimator != null) {
+ mAnimator.cancel();
+ mAnimator = null;
+ }
+ mAnimationProgress = ANIMATION_PROGRESS_STOPPED;
+
+ invalidateSelf();
+ return true;
+ }
+
+ /**
+ * Runs the finish animation if it is has not been run after last level change.
+ */
+ public void maybePerformFinishedAnimation() {
+ if (mAnimationProgress > ANIMATION_PROGRESS_STOPPED) {
+ return;
+ }
+ if (mAnimator != null) {
+ mAnimator.cancel();
+ }
+ setAnimationProgress(ANIMATION_PROGRESS_STARTED);
+ mAnimator = ObjectAnimator.ofFloat(this, "animationProgress",
+ ANIMATION_PROGRESS_STARTED, ANIMATION_PROGRESS_COMPLETED);
+ mAnimator.start();
+ }
+
+ public void setAnimationProgress(float progress) {
+ if (progress != mAnimationProgress) {
+ mAnimationProgress = progress;
+ invalidateSelf();
+ }
+ }
+
+ public float getAnimationProgress() {
+ return mAnimationProgress;
+ }
+}