summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSunny Goyal <sunnygoyal@google.com>2014-07-09 07:09:28 (GMT)
committerSunny Goyal <sunnygoyal@google.com>2014-07-16 20:37:56 (GMT)
commit3484638cad97e255a412b0489a63873fb3ca4218 (patch)
treedbc210a2298262bb8df5c1149a80d35e7c71af7f
parentf599ccfe96eae7e4854bddfedd3df945feb9b7f5 (diff)
downloadandroid_packages_apps_Trebuchet-3484638cad97e255a412b0489a63873fb3ca4218.zip
android_packages_apps_Trebuchet-3484638cad97e255a412b0489a63873fb3ca4218.tar.gz
android_packages_apps_Trebuchet-3484638cad97e255a412b0489a63873fb3ca4218.tar.bz2
Adding a circular progress bar for preloader icons
Change-Id: I1b5ba61c01a16a8cb5d3f9e31f827f8c99a1ffc9
-rw-r--r--proguard.flags5
-rw-r--r--res/drawable-xxhdpi/bg_preloader.pngbin0 -> 3785 bytes
-rw-r--r--res/drawable-xxhdpi/bg_preloader_progress.pngbin0 -> 1131 bytes
-rw-r--r--res/values/integers.xml22
-rw-r--r--src/com/android/launcher3/BubbleTextView.java28
-rw-r--r--src/com/android/launcher3/FolderIcon.java9
-rw-r--r--src/com/android/launcher3/LauncherModel.java1
-rw-r--r--src/com/android/launcher3/PreloadIconDrawable.java168
-rw-r--r--src/com/android/launcher3/ShortcutInfo.java11
9 files changed, 208 insertions, 36 deletions
diff --git a/proguard.flags b/proguard.flags
index a922e91..0b28c0e 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -52,3 +52,8 @@
-keep class com.android.launcher3.MemoryDumpActivity {
*;
}
+
+-keep class com.android.launcher3.PreloadIconDrawable {
+ public float getAnimationProgress();
+ public void setAnimationProgress(float);
+}
diff --git a/res/drawable-xxhdpi/bg_preloader.png b/res/drawable-xxhdpi/bg_preloader.png
new file mode 100644
index 0000000..56b8060
--- /dev/null
+++ b/res/drawable-xxhdpi/bg_preloader.png
Binary files differ
diff --git a/res/drawable-xxhdpi/bg_preloader_progress.png b/res/drawable-xxhdpi/bg_preloader_progress.png
new file mode 100644
index 0000000..443afe9
--- /dev/null
+++ b/res/drawable-xxhdpi/bg_preloader_progress.png
Binary files differ
diff --git a/res/values/integers.xml b/res/values/integers.xml
deleted file mode 100644
index 7d26d85..0000000
--- a/res/values/integers.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-* Copyright (C) 2014 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
--->
-
-<resources>
- <integer name="promise_icon_alpha">127</integer>
-</resources> \ No newline at end of file
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 57dcea0..3f619a8 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -136,7 +136,8 @@ public class BubbleTextView extends TextView {
setContentDescription(info.contentDescription);
}
setTag(info);
- if (info.isPromise()) {
+
+ if (info.wasPromise) {
applyState();
}
}
@@ -431,42 +432,55 @@ public class BubbleTextView extends TextView {
}
public void applyState() {
- int alpha = getResources().getInteger(R.integer.promise_icon_alpha);
+ final int progressLevel;
final int state = getState();
if (DEBUG) Log.d(TAG, "applying icon state: " + state);
switch(state) {
case ShortcutInfo.PACKAGE_STATE_DEFAULT:
super.setText(mDefaultText);
- alpha = 255;
+ progressLevel = 100;
break;
case ShortcutInfo.PACKAGE_STATE_ENQUEUED:
setText(R.string.package_state_enqueued);
+ progressLevel = 0;
break;
case ShortcutInfo.PACKAGE_STATE_DOWNLOADING:
setText(R.string.package_state_downloading);
+ // TODO(sunnygoyal): fix progress
+ progressLevel = 30;
break;
case ShortcutInfo.PACKAGE_STATE_INSTALLING:
setText(R.string.package_state_installing);
+ progressLevel = 100;
break;
case ShortcutInfo.PACKAGE_STATE_ERROR:
setText(R.string.package_state_error);
+ progressLevel = 0;
break;
case ShortcutInfo.PACKAGE_STATE_UNKNOWN:
default:
+ progressLevel = 0;
setText(R.string.package_state_unknown);
break;
}
- if (DEBUG) Log.d(TAG, "setting icon alpha to: " + alpha);
+
Drawable[] drawables = getCompoundDrawables();
- for (int i = 0; i < drawables.length; i++) {
- if (drawables[i] != null) {
- drawables[i].setAlpha(alpha);
+ Drawable top = drawables[1];
+ if ((top != null) && !(top instanceof PreloadIconDrawable)) {
+ top = new PreloadIconDrawable(top, getResources());
+ setCompoundDrawables(drawables[0], top, drawables[2], drawables[3]);
+ }
+ if (top != null) {
+ top.setLevel(progressLevel);
+ if ((top instanceof PreloadIconDrawable)
+ && (state == ShortcutInfo.PACKAGE_STATE_DEFAULT)) {
+ ((PreloadIconDrawable) top).maybePerformFinishedAnimation();
}
}
}
diff --git a/src/com/android/launcher3/FolderIcon.java b/src/com/android/launcher3/FolderIcon.java
index ab8976a..4f674f5 100644
--- a/src/com/android/launcher3/FolderIcon.java
+++ b/src/com/android/launcher3/FolderIcon.java
@@ -605,7 +605,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
computePreviewDrawingParams(mAnimParams.drawable);
} else {
v = (TextView) items.get(0);
- d = v.getCompoundDrawables()[1];
+ d = getTopDrawable(v);
computePreviewDrawingParams(d);
}
@@ -614,7 +614,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
for (int i = nItemsInPreview - 1; i >= 0; i--) {
v = (TextView) items.get(i);
if (!mHiddenItems.contains(v.getTag())) {
- d = v.getCompoundDrawables()[1];
+ d = getTopDrawable(v);
mParams = computePreviewItemDrawingParams(i, mParams);
mParams.drawable = d;
drawPreviewItem(canvas, mParams);
@@ -625,6 +625,11 @@ public class FolderIcon extends FrameLayout implements FolderListener {
}
}
+ private Drawable getTopDrawable(TextView v) {
+ Drawable d = v.getCompoundDrawables()[1];
+ return (d instanceof PreloadIconDrawable) ? ((PreloadIconDrawable) d).mIcon : d;
+ }
+
private void animateFirstItem(final Drawable d, int duration, final boolean reverse,
final Runnable onCompleteRunnable) {
final PreviewItemDrawingParams finalParams = computePreviewItemDrawingParams(0, null);
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index f1e73eb..b01db71 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -3047,6 +3047,7 @@ public class LauncherModel extends BroadcastReceiver
info.setIcon(mIconCache.getIcon(intent, info.title.toString(), info.user));
info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
info.restoredIntent = intent;
+ info.wasPromise = true;
info.setState(ShortcutInfo.PACKAGE_STATE_UNKNOWN);
return info;
}
diff --git a/src/com/android/launcher3/PreloadIconDrawable.java b/src/com/android/launcher3/PreloadIconDrawable.java
new file mode 100644
index 0000000..d9365cc
--- /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;
+ }
+}
diff --git a/src/com/android/launcher3/ShortcutInfo.java b/src/com/android/launcher3/ShortcutInfo.java
index d2573a4..7e1f0d6 100644
--- a/src/com/android/launcher3/ShortcutInfo.java
+++ b/src/com/android/launcher3/ShortcutInfo.java
@@ -16,13 +16,9 @@
package com.android.launcher3;
-import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Bitmap;
import android.util.Log;
@@ -96,6 +92,11 @@ public class ShortcutInfo extends ItemInfo {
*/
Intent restoredIntent;
+ /**
+ * This is set once to indicate that it was a promise info at some point of its life.
+ */
+ boolean wasPromise = false;
+
ShortcutInfo() {
itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_SHORTCUT;
}
@@ -119,7 +120,7 @@ public class ShortcutInfo extends ItemInfo {
}
}
- ShortcutInfo(Intent intent, CharSequence title, String contentDescrition,
+ ShortcutInfo(Intent intent, CharSequence title, String contentDescription,
Bitmap icon, UserHandleCompat user) {
this();
this.intent = intent;