From b40b98db3a6eb7f75207a835b4c637d2b53de09a Mon Sep 17 00:00:00 2001 From: Schneider Victor-tulias Date: Thu, 21 Jan 2021 14:41:07 -0800 Subject: [PATCH] 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) --- src/com/android/launcher3/BubbleTextView.java | 88 ++++++++++++------- .../android/launcher3/FastBitmapDrawable.java | 6 +- .../launcher3/allapps/AllAppsStore.java | 2 +- .../graphics/PreloadIconDrawable.java | 44 +++++++++- .../launcher3/icons/ClockDrawableWrapper.java | 2 +- .../launcher3/views/FloatingIconView.java | 25 +++++- 6 files changed, 124 insertions(+), 43 deletions(-) diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index 22eb15a8e2..575d6cd8e6 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -301,7 +301,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, verifyHighRes(); if ((info.runtimeStatusFlags & ItemInfoWithIcon.FLAG_SHOW_DOWNLOAD_PROGRESS_MASK) != 0) { - applyProgressLevel(info.getProgressLevel()); + applyProgressLevel(); } applyDotState(info, false /* animate */); } @@ -603,21 +603,20 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, * 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 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, /** 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)); - } - 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; + preloadIconDrawable = makePreloadIcon(); + setIcon(preloadIconDrawable); } + 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 139d4a85e4..b1fe4a235c 100644 --- a/src/com/android/launcher3/FastBitmapDrawable.java +++ b/src/com/android/launcher3/FastBitmapDrawable.java @@ -276,15 +276,15 @@ public class FastBitmapDrawable extends Drawable { @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 00bdb70c4a..769cb5e31b 100644 --- a/src/com/android/launcher3/allapps/AllAppsStore.java +++ b/src/com/android/launcher3/allapps/AllAppsStore.java @@ -154,7 +154,7 @@ public class AllAppsStore { 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 9971990267..304d49692e 100644 --- a/src/com/android/launcher3/graphics/PreloadIconDrawable.java +++ b/src/com/android/launcher3/graphics/PreloadIconDrawable.java @@ -105,6 +105,10 @@ public class PreloadIconDrawable extends FastBitmapDrawable { 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 @@ public class PreloadIconDrawable extends FastBitmapDrawable { 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 class PreloadIconDrawable extends FastBitmapDrawable { 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 b7dd092ab4..1bd252ba45 100644 --- a/src/com/android/launcher3/icons/ClockDrawableWrapper.java +++ b/src/com/android/launcher3/icons/ClockDrawableWrapper.java @@ -308,7 +308,7 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap 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 1857c5a7b4..23c3722aca 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.Utilities; 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 @@ public class FloatingIconView extends FrameLayout implements @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 @@ public class FloatingIconView extends FrameLayout implements } 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();