From 3484638cad97e255a412b0489a63873fb3ca4218 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Wed, 9 Jul 2014 00:09:28 -0700 Subject: Adding a circular progress bar for preloader icons Change-Id: I1b5ba61c01a16a8cb5d3f9e31f827f8c99a1ffc9 --- src/com/android/launcher3/PreloadIconDrawable.java | 168 +++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 src/com/android/launcher3/PreloadIconDrawable.java (limited to 'src/com/android/launcher3/PreloadIconDrawable.java') 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; + } +} -- cgit v1.2.3