Update FloatingIconView to display PreloadIconDrawables during swipe home animations.
Swiping up to go home on an app that is downloading incrementally would cause a jittery animation. Updated FloatingIconView to animate directly to a PreloadIconDrawable.
Demo: https://drive.google.com/file/d/1ddr8OGR4c1ZneyQ0VkkAAxGpwNcP8Wyn/view?usp=sharing
Fixes: 177685929
Test: manual
Change-Id: I4cd2daa18f6d3fed42a9b666063e0b1c1c46e5d9
(cherry picked from commit b8cab8d8786a7de6adfcd5b77af9408e832ed0c2)
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 22eb15a..575d6cd 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -301,7 +301,7 @@
verifyHighRes();
if ((info.runtimeStatusFlags & ItemInfoWithIcon.FLAG_SHOW_DOWNLOAD_PROGRESS_MASK) != 0) {
- applyProgressLevel(info.getProgressLevel());
+ applyProgressLevel();
}
applyDotState(info, false /* animate */);
}
@@ -603,21 +603,20 @@
* with the total download progress.
*/
public void applyLoadingState(boolean promiseStateChanged) {
- if (getTag() instanceof WorkspaceItemInfo) {
+ if (getTag() instanceof ItemInfoWithIcon) {
WorkspaceItemInfo info = (WorkspaceItemInfo) getTag();
- int progressLevel = info.getProgressLevel();
if ((info.runtimeStatusFlags & ItemInfoWithIcon.FLAG_INCREMENTAL_DOWNLOAD_ACTIVE)
!= 0) {
- updateProgressBarUi(progressLevel, progressLevel == 100);
+ updateProgressBarUi(info.getProgressLevel() == 100);
} else if (info.hasPromiseIconUi() || (info.runtimeStatusFlags
- & ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE) != 0) {
- updateProgressBarUi(progressLevel, promiseStateChanged);
+ & ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE) != 0) {
+ updateProgressBarUi(promiseStateChanged);
}
}
}
- private void updateProgressBarUi(int progressLevel, boolean maybePerformFinishedAnimation) {
- PreloadIconDrawable preloadDrawable = applyProgressLevel(progressLevel);
+ private void updateProgressBarUi(boolean maybePerformFinishedAnimation) {
+ PreloadIconDrawable preloadDrawable = applyProgressLevel();
if (preloadDrawable != null && maybePerformFinishedAnimation) {
preloadDrawable.maybePerformFinishedAnimation();
}
@@ -625,38 +624,59 @@
/** Applies the given progress level to the this icon's progress bar. */
@Nullable
- public PreloadIconDrawable applyProgressLevel(int progressLevel) {
- if (getTag() instanceof ItemInfoWithIcon) {
- ItemInfoWithIcon info = (ItemInfoWithIcon) getTag();
- if (progressLevel >= 100) {
- setContentDescription(info.contentDescription != null
- ? info.contentDescription : "");
- } else if (progressLevel > 0) {
- setContentDescription(getContext()
- .getString(R.string.app_downloading_title, info.title,
- NumberFormat.getPercentInstance().format(progressLevel * 0.01)));
+ public PreloadIconDrawable applyProgressLevel() {
+ if (!(getTag() instanceof ItemInfoWithIcon)) {
+ return null;
+ }
+
+ ItemInfoWithIcon info = (ItemInfoWithIcon) getTag();
+ int progressLevel = info.getProgressLevel();
+ if (progressLevel >= 100) {
+ setContentDescription(info.contentDescription != null
+ ? info.contentDescription : "");
+ } else if (progressLevel > 0) {
+ setContentDescription(getContext()
+ .getString(R.string.app_downloading_title, info.title,
+ NumberFormat.getPercentInstance().format(progressLevel * 0.01)));
+ } else {
+ setContentDescription(getContext()
+ .getString(R.string.app_waiting_download_title, info.title));
+ }
+ if (mIcon != null) {
+ PreloadIconDrawable preloadIconDrawable;
+ if (mIcon instanceof PreloadIconDrawable) {
+ preloadIconDrawable = (PreloadIconDrawable) mIcon;
+ preloadIconDrawable.setLevel(progressLevel);
+ preloadIconDrawable.setIsDisabled(!info.isAppStartable());
} else {
- setContentDescription(getContext()
- .getString(R.string.app_waiting_download_title, info.title));
+ preloadIconDrawable = makePreloadIcon();
+ setIcon(preloadIconDrawable);
}
- if (mIcon != null) {
- final PreloadIconDrawable preloadDrawable;
- if (mIcon instanceof PreloadIconDrawable) {
- preloadDrawable = (PreloadIconDrawable) mIcon;
- preloadDrawable.setLevel(progressLevel);
- preloadDrawable.setIsDisabled(!info.isAppStartable());
- } else {
- preloadDrawable = newPendingIcon(getContext(), info);
- preloadDrawable.setLevel(progressLevel);
- preloadDrawable.setIsDisabled(!info.isAppStartable());
- setIcon(preloadDrawable);
- }
- return preloadDrawable;
- }
+ return preloadIconDrawable;
}
return null;
}
+ /**
+ * Creates a PreloadIconDrawable with the appropriate progress level without mutating this
+ * object.
+ */
+ @Nullable
+ public PreloadIconDrawable makePreloadIcon() {
+ if (!(getTag() instanceof ItemInfoWithIcon)) {
+ return null;
+ }
+
+ ItemInfoWithIcon info = (ItemInfoWithIcon) getTag();
+ int progressLevel = info.getProgressLevel();
+ final PreloadIconDrawable preloadDrawable = newPendingIcon(getContext(), info);
+
+ preloadDrawable.setLevel(progressLevel);
+ preloadDrawable.setIsDisabled(!info.isAppStartable());
+
+ return preloadDrawable;
+ }
+
public void applyDotState(ItemInfo itemInfo, boolean animate) {
if (mIcon instanceof FastBitmapDrawable) {
boolean wasDotted = mDotInfo != null;
diff --git a/src/com/android/launcher3/FastBitmapDrawable.java b/src/com/android/launcher3/FastBitmapDrawable.java
index 139d4a8..b1fe4a2 100644
--- a/src/com/android/launcher3/FastBitmapDrawable.java
+++ b/src/com/android/launcher3/FastBitmapDrawable.java
@@ -276,15 +276,15 @@
@Override
public ConstantState getConstantState() {
- return new MyConstantState(mBitmap, mIconColor, mIsDisabled);
+ return new FastBitmapConstantState(mBitmap, mIconColor, mIsDisabled);
}
- protected static class MyConstantState extends ConstantState {
+ protected static class FastBitmapConstantState extends ConstantState {
protected final Bitmap mBitmap;
protected final int mIconColor;
protected final boolean mIsDisabled;
- public MyConstantState(Bitmap bitmap, int color, boolean isDisabled) {
+ public FastBitmapConstantState(Bitmap bitmap, int color, boolean isDisabled) {
mBitmap = bitmap;
mIconColor = color;
mIsDisabled = isDisabled;
diff --git a/src/com/android/launcher3/allapps/AllAppsStore.java b/src/com/android/launcher3/allapps/AllAppsStore.java
index 00bdb70..769cb5e 100644
--- a/src/com/android/launcher3/allapps/AllAppsStore.java
+++ b/src/com/android/launcher3/allapps/AllAppsStore.java
@@ -154,7 +154,7 @@
public void updateProgressBar(AppInfo app) {
updateAllIcons((child) -> {
if (child.getTag() == app) {
- child.applyProgressLevel(app.getProgressLevel());
+ child.applyProgressLevel();
}
});
}
diff --git a/src/com/android/launcher3/graphics/PreloadIconDrawable.java b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
index 9971990..304d496 100644
--- a/src/com/android/launcher3/graphics/PreloadIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
@@ -105,6 +105,10 @@
private ObjectAnimator mCurrentAnim;
public PreloadIconDrawable(ItemInfoWithIcon info, Context context) {
+ this(info, IconPalette.getPreloadProgressColor(context, info.bitmap.color));
+ }
+
+ public PreloadIconDrawable(ItemInfoWithIcon info, int indicatorColor) {
super(info.bitmap);
mItem = info;
mShapePath = getShapePath();
@@ -114,7 +118,7 @@
mProgressPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
mProgressPaint.setStyle(Paint.Style.STROKE);
mProgressPaint.setStrokeCap(Paint.Cap.ROUND);
- mIndicatorColor = IconPalette.getPreloadProgressColor(context, mIconColor);
+ mIndicatorColor = indicatorColor;
setInternalProgress(0);
@@ -297,4 +301,42 @@
public static PreloadIconDrawable newPendingIcon(Context context, ItemInfoWithIcon info) {
return new PreloadIconDrawable(info, context);
}
+
+ @Override
+ public ConstantState getConstantState() {
+ return new PreloadIconConstantState(
+ mBitmap, mIconColor, !mItem.isAppStartable(), mItem, mIndicatorColor);
+ }
+
+ protected static class PreloadIconConstantState extends FastBitmapConstantState {
+
+ protected final ItemInfoWithIcon mInfo;
+ protected final int mIndicatorColor;
+ protected final int mLevel;
+
+ public PreloadIconConstantState(
+ Bitmap bitmap,
+ int iconColor,
+ boolean isDisabled,
+ ItemInfoWithIcon info,
+ int indicatorcolor) {
+ super(bitmap, iconColor, isDisabled);
+ mInfo = info;
+ mIndicatorColor = indicatorcolor;
+ mLevel = info.getProgressLevel();
+ }
+
+ @Override
+ public PreloadIconDrawable newDrawable() {
+ PreloadIconDrawable drawable = new PreloadIconDrawable(mInfo, mIndicatorColor);
+ drawable.setLevel(mLevel);
+ drawable.setIsDisabled(mIsDisabled);
+ return drawable;
+ }
+
+ @Override
+ public int getChangingConfigurations() {
+ return 0;
+ }
+ }
}
diff --git a/src/com/android/launcher3/icons/ClockDrawableWrapper.java b/src/com/android/launcher3/icons/ClockDrawableWrapper.java
index b7dd092..1bd252b 100644
--- a/src/com/android/launcher3/icons/ClockDrawableWrapper.java
+++ b/src/com/android/launcher3/icons/ClockDrawableWrapper.java
@@ -308,7 +308,7 @@
return new ClockConstantState(mInfo, isDisabled());
}
- private static class ClockConstantState extends MyConstantState {
+ private static class ClockConstantState extends FastBitmapConstantState {
private final ClockBitmapInfo mInfo;
diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java
index 1857c5a..23c3722 100644
--- a/src/com/android/launcher3/views/FloatingIconView.java
+++ b/src/com/android/launcher3/views/FloatingIconView.java
@@ -51,8 +51,10 @@
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.dragndrop.FolderAdaptiveIcon;
import com.android.launcher3.folder.FolderIcon;
+import com.android.launcher3.graphics.PreloadIconDrawable;
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.shortcuts.DeepShortcutView;
@@ -252,12 +254,26 @@
@SuppressWarnings("WrongThread")
private static void getIconResult(Launcher l, View originalView, ItemInfo info, RectF pos,
IconLoadResult iconLoadResult) {
- Drawable drawable = null;
+ Drawable drawable;
+ Drawable btvIcon;
Drawable badge = null;
boolean supportsAdaptiveIcons = ADAPTIVE_ICON_WINDOW_ANIM.get()
&& !info.isDisabled(); // Use original icon for disabled icons.
- Drawable btvIcon = originalView instanceof BubbleTextView
- ? ((BubbleTextView) originalView).getIcon() : null;
+
+ if (originalView instanceof BubbleTextView) {
+ BubbleTextView btv = (BubbleTextView) originalView;
+
+ if (info instanceof ItemInfoWithIcon
+ && (((ItemInfoWithIcon) info).runtimeStatusFlags
+ & ItemInfoWithIcon.FLAG_SHOW_DOWNLOAD_PROGRESS_MASK) != 0) {
+ btvIcon = btv.makePreloadIcon();
+ } else {
+ btvIcon = btv.getIcon();
+ }
+ } else {
+ btvIcon = null;
+ }
+
if (info instanceof SystemShortcut) {
if (originalView instanceof ImageView) {
drawable = ((ImageView) originalView).getDrawable();
@@ -266,6 +282,9 @@
} else {
drawable = originalView.getBackground();
}
+ } else if (btvIcon instanceof PreloadIconDrawable) {
+ // Force the progress bar to display.
+ drawable = btvIcon;
} else {
int width = (int) pos.width();
int height = (int) pos.height();