summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3/folder
diff options
context:
space:
mode:
authorJon Miranda <jonmiranda@google.com>2017-07-06 09:55:50 -0700
committerJon Miranda <jonmiranda@google.com>2017-07-06 12:20:56 -0700
commit6c5d10261eceaf1b57bce82e4e31d272bad2c349 (patch)
treef6ecd49c9d9f3feb2f336a020e5f4c841df5e7d4 /src/com/android/launcher3/folder
parente393c809e637b16bd9af8a2fc7cd30f0ffed020e (diff)
downloadandroid_packages_apps_Trebuchet-6c5d10261eceaf1b57bce82e4e31d272bad2c349.tar.gz
android_packages_apps_Trebuchet-6c5d10261eceaf1b57bce82e4e31d272bad2c349.tar.bz2
android_packages_apps_Trebuchet-6c5d10261eceaf1b57bce82e4e31d272bad2c349.zip
Move the PreviewItem drawing/animation logic to PreviewItemManager.
We want this refactor in O-DR since we will be adding more animations: - closing from a non-first page (ag/2455887 b/36022592) - new on-drop animations *if we end up removing the permutation logic. Bug: 36022592 Change-Id: I82b8f5f5033d4fd9bd50fbe414b0fb721891d043
Diffstat (limited to 'src/com/android/launcher3/folder')
-rw-r--r--src/com/android/launcher3/folder/Folder.java2
-rw-r--r--src/com/android/launcher3/folder/FolderIcon.java209
-rw-r--r--src/com/android/launcher3/folder/FolderPreviewItemAnim.java30
-rw-r--r--src/com/android/launcher3/folder/PreviewItemManager.java216
4 files changed, 261 insertions, 196 deletions
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index f68b394c1..afbf9f2a2 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -1280,7 +1280,7 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC
};
View finalChild = mContent.getLastItem();
if (finalChild != null) {
- mFolderIcon.performDestroyAnimation(finalChild, onCompleteRunnable);
+ mFolderIcon.performDestroyAnimation(onCompleteRunnable);
} else {
onCompleteRunnable.run();
}
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index 3a0e71fa5..7fdacc094 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -37,7 +37,6 @@ import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
-import android.widget.TextView;
import com.android.launcher3.Alarm;
import com.android.launcher3.AppInfo;
@@ -71,6 +70,8 @@ import com.android.launcher3.widget.PendingAddShortcutInfo;
import java.util.ArrayList;
import java.util.List;
+import static com.android.launcher3.folder.PreviewItemManager.INITIAL_ITEM_ANIMATION_DURATION;
+
/**
* An icon that can appear on in the workspace representing an {@link Folder}.
*/
@@ -87,9 +88,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
private CheckLongPressHelper mLongPressHelper;
private StylusEventHelper mStylusEventHelper;
- private static final int DROP_IN_ANIMATION_DURATION = 400;
- private static final int INITIAL_ITEM_ANIMATION_DURATION = 350;
- private static final int FINAL_ITEM_ANIMATION_DURATION = 200;
+ static final int DROP_IN_ANIMATION_DURATION = 400;
// Flag whether the folder should open itself when an item is dragged over is enabled.
public static final boolean SPRING_LOADING_ENABLED = true;
@@ -99,27 +98,19 @@ public class FolderIcon extends FrameLayout implements FolderListener {
@Thunk BubbleTextView mFolderName;
- // These variables are all associated with the drawing of the preview; they are stored
- // as member variables for shared usage and to avoid computation on each frame
- private float mIntrinsicIconSize = -1;
- private int mTotalWidth = -1;
- private int mPrevTopPadding = -1;
-
PreviewBackground mBackground = new PreviewBackground();
private boolean mBackgroundIsVisible = true;
- private PreviewLayoutRule mPreviewLayoutRule;
+ FolderIconPreviewVerifier mPreviewVerifier;
+ PreviewLayoutRule mPreviewLayoutRule;
+ private PreviewItemManager mPreviewItemManager;
+ private PreviewItemDrawingParams mTmpParams = new PreviewItemDrawingParams(0, 0, 0, 0);
boolean mAnimating = false;
private Rect mTempBounds = new Rect();
private float mSlop;
- FolderIconPreviewVerifier mPreviewVerifier;
- private PreviewItemDrawingParams mTmpParams = new PreviewItemDrawingParams(0, 0, 0, 0);
- private ArrayList<PreviewItemDrawingParams> mDrawingParams = new ArrayList<>();
- private Drawable mReferenceDrawable = null;
-
private Alarm mOpenAlarm = new Alarm();
private FolderBadgeInfo mBadgeInfo = new FolderBadgeInfo();
@@ -158,6 +149,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
new StackFolderIconLayoutRule() :
new ClippedFolderIconLayoutRule();
mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
+ mPreviewItemManager = new PreviewItemManager(this);
}
public static FolderIcon fromXml(int resId, Launcher launcher, ViewGroup group,
@@ -213,7 +205,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
private void setFolder(Folder folder) {
mFolder = folder;
mPreviewVerifier = new FolderIconPreviewVerifier(mLauncher.getDeviceProfile().inv);
- updateItemDrawingParams(false);
+ mPreviewItemManager.updateItemDrawingParams(false);
}
private boolean willAcceptItem(ItemInfo item) {
@@ -254,40 +246,28 @@ public class FolderIcon extends FrameLayout implements FolderListener {
}
};
- public Drawable prepareCreate(final View destView) {
- Drawable animateDrawable = ((TextView) destView).getCompoundDrawables()[1];
- computePreviewDrawingParams(animateDrawable.getIntrinsicWidth(),
- destView.getMeasuredWidth());
- return animateDrawable;
+ public Drawable prepareCreateAnimation(final View destView) {
+ return mPreviewItemManager.prepareCreateAnimation(destView);
}
public void performCreateAnimation(final ShortcutInfo destInfo, final View destView,
final ShortcutInfo srcInfo, final DragView srcView, Rect dstRect,
float scaleRelativeToDragLayer, Runnable postAnimationRunnable) {
-
- // These correspond two the drawable and view that the icon was dropped _onto_
- Drawable animateDrawable = prepareCreate(destView);
-
- mReferenceDrawable = animateDrawable;
-
+ prepareCreateAnimation(destView);
addItem(destInfo);
// This will animate the first item from it's position as an icon into its
// position as the first item in the preview
- animateFirstItem(animateDrawable, INITIAL_ITEM_ANIMATION_DURATION, false, null);
+ mPreviewItemManager.createFirstItemAnimation(false /* reverse */, null)
+ .start();
// This will animate the dragView (srcView) into the new folder
onDrop(srcInfo, srcView, dstRect, scaleRelativeToDragLayer, 1, postAnimationRunnable);
}
- public void performDestroyAnimation(final View finalView, Runnable onCompleteRunnable) {
- Drawable animateDrawable = ((TextView) finalView).getCompoundDrawables()[1];
- computePreviewDrawingParams(animateDrawable.getIntrinsicWidth(),
- finalView.getMeasuredWidth());
-
- // This will animate the first item from it's position as an icon into its
- // position as the first item in the preview
- animateFirstItem(animateDrawable, FINAL_ITEM_ANIMATION_DURATION, true,
- onCompleteRunnable);
+ public void performDestroyAnimation(Runnable onCompleteRunnable) {
+ // This will animate the final item in the preview to be full size.
+ mPreviewItemManager.createFirstItemAnimation(true /* reverse */, onCompleteRunnable)
+ .start();
}
public void onDragExit() {
@@ -296,7 +276,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
}
private void onDrop(final ShortcutInfo item, DragView animateView, Rect finalRect,
- float scaleRelativeToDragLayer, int index, Runnable postAnimationRunnable) {
+ float scaleRelativeToDragLayer, final int index, Runnable postAnimationRunnable) {
item.cellX = -1;
item.cellY = -1;
@@ -342,12 +322,10 @@ public class FolderIcon extends FrameLayout implements FolderListener {
addItem(item);
mFolder.hideItem(item);
- final PreviewItemDrawingParams params = index < mDrawingParams.size() ?
- mDrawingParams.get(index) : null;
- if (params != null) params.hidden = true;
+ mPreviewItemManager.hidePreviewItem(index, true);
postDelayed(new Runnable() {
public void run() {
- if (params != null) params.hidden = false;
+ mPreviewItemManager.hidePreviewItem(index, false);
mFolder.showItem(item);
invalidate();
}
@@ -369,25 +347,6 @@ public class FolderIcon extends FrameLayout implements FolderListener {
onDrop(item, d.dragView, null, 1.0f, mInfo.contents.size(), d.postAnimationRunnable);
}
- private void computePreviewDrawingParams(int drawableSize, int totalSize) {
- if (mIntrinsicIconSize != drawableSize || mTotalWidth != totalSize ||
- mPrevTopPadding != getPaddingTop()) {
- mIntrinsicIconSize = drawableSize;
- mTotalWidth = totalSize;
- mPrevTopPadding = getPaddingTop();
-
- mBackground.setup(mLauncher, this, mTotalWidth, getPaddingTop());
- mPreviewLayoutRule.init(mBackground.previewSize, mIntrinsicIconSize,
- Utilities.isRtl(getResources()));
-
- updateItemDrawingParams(false);
- }
- }
-
- private void computePreviewDrawingParams(Drawable d) {
- computePreviewDrawingParams(d.getIntrinsicWidth(), getMeasuredWidth());
- }
-
public void setBadgeInfo(FolderBadgeInfo badgeInfo) {
updateBadgeScale(mBadgeInfo.hasBadge(), badgeInfo.hasBadge());
mBadgeInfo = badgeInfo;
@@ -421,56 +380,21 @@ public class FolderIcon extends FrameLayout implements FolderListener {
}
private float getLocalCenterForIndex(int index, int curNumItems, int[] center) {
- mTmpParams = computePreviewItemDrawingParams(
+ mTmpParams = mPreviewItemManager.computePreviewItemDrawingParams(
Math.min(mPreviewLayoutRule.maxNumItems(), index), curNumItems, mTmpParams);
mTmpParams.transX += mBackground.basePreviewOffsetX;
mTmpParams.transY += mBackground.basePreviewOffsetY;
- float offsetX = mTmpParams.transX + (mTmpParams.scale * mIntrinsicIconSize) / 2;
- float offsetY = mTmpParams.transY + (mTmpParams.scale * mIntrinsicIconSize) / 2;
+
+ float intrinsicIconSize = mPreviewItemManager.getIntrinsicIconSize();
+ float offsetX = mTmpParams.transX + (mTmpParams.scale * intrinsicIconSize) / 2;
+ float offsetY = mTmpParams.transY + (mTmpParams.scale * intrinsicIconSize) / 2;
center[0] = Math.round(offsetX);
center[1] = Math.round(offsetY);
return mTmpParams.scale;
}
- PreviewItemDrawingParams computePreviewItemDrawingParams(int index, int curNumItems,
- PreviewItemDrawingParams params) {
- // We use an index of -1 to represent an icon on the workspace for the destroy and
- // create animations
- if (index == -1) {
- return getFinalIconParams(params);
- }
- return mPreviewLayoutRule.computePreviewItemDrawingParams(index, curNumItems, params);
- }
-
- private PreviewItemDrawingParams getFinalIconParams(PreviewItemDrawingParams params) {
- float iconSize = mLauncher.getDeviceProfile().iconSizePx;
-
- final float scale = iconSize / mReferenceDrawable.getIntrinsicWidth();
- final float trans = (mBackground.previewSize - iconSize) / 2;
-
- params.update(trans, trans, scale);
- return params;
- }
-
- private void drawPreviewItem(Canvas canvas, PreviewItemDrawingParams params) {
- canvas.save(Canvas.MATRIX_SAVE_FLAG);
- canvas.translate(params.transX, params.transY);
- canvas.scale(params.scale, params.scale);
- Drawable d = params.drawable;
-
- if (d != null) {
- Rect bounds = d.getBounds();
- canvas.save();
- canvas.translate(-bounds.left, -bounds.top);
- canvas.scale(mIntrinsicIconSize / bounds.width(), mIntrinsicIconSize / bounds.height());
- d.draw(canvas);
- canvas.restore();
- }
- canvas.restore();
- }
-
public void setFolderBackground(PreviewBackground bg) {
mBackground = bg;
mBackground.setInvalidateDelegate(this);
@@ -487,10 +411,6 @@ public class FolderIcon extends FrameLayout implements FolderListener {
if (!mBackgroundIsVisible) return;
- if (mReferenceDrawable != null) {
- computePreviewDrawingParams(mReferenceDrawable);
- }
-
if (!mBackground.drawingDelegated()) {
mBackground.drawBackground(canvas);
}
@@ -512,14 +432,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
// The items are drawn in coordinates relative to the preview offset
canvas.translate(mBackground.basePreviewOffsetX, mBackground.basePreviewOffsetY);
-
- // The first item should be drawn last (ie. on top of later items)
- for (int i = mDrawingParams.size() - 1; i >= 0; i--) {
- PreviewItemDrawingParams p = mDrawingParams.get(i);
- if (!p.hidden) {
- drawPreviewItem(canvas, p);
- }
- }
+ mPreviewItemManager.draw(canvas);
canvas.translate(-mBackground.basePreviewOffsetX, -mBackground.basePreviewOffsetY);
if (mPreviewLayoutRule.clipToBackground() && canvas.isHardwareAccelerated()) {
@@ -546,19 +459,6 @@ public class FolderIcon extends FrameLayout implements FolderListener {
}
}
- private void animateFirstItem(final Drawable d, int duration, final boolean reverse,
- final Runnable onCompleteRunnable) {
- FolderPreviewItemAnim anim;
- if (!reverse) {
- anim = new FolderPreviewItemAnim(this, mDrawingParams.get(0), -1, -1, 0, 2, duration,
- onCompleteRunnable);
- } else {
- anim = new FolderPreviewItemAnim(this, mDrawingParams.get(0), 0, 2, -1, -1, duration,
- onCompleteRunnable);
- }
- anim.start();
- }
-
public void setTextVisible(boolean visible) {
if (visible) {
mFolderName.setVisibility(VISIBLE);
@@ -591,63 +491,12 @@ public class FolderIcon extends FrameLayout implements FolderListener {
@Override
protected boolean verifyDrawable(@NonNull Drawable who) {
- for (int i = 0; i < mDrawingParams.size(); i++) {
- if (mDrawingParams.get(i).drawable == who) {
- return true;
- }
- }
- return super.verifyDrawable(who);
- }
-
- private void updateItemDrawingParams(boolean animate) {
- List<BubbleTextView> items = getItemsToDisplay();
- int nItemsInPreview = items.size();
-
- int prevNumItems = mDrawingParams.size();
-
- // We adjust the size of the list to match the number of items in the preview
- while (nItemsInPreview < mDrawingParams.size()) {
- mDrawingParams.remove(mDrawingParams.size() - 1);
- }
- while (nItemsInPreview > mDrawingParams.size()) {
- mDrawingParams.add(new PreviewItemDrawingParams(0, 0, 0, 0));
- }
-
- for (int i = 0; i < mDrawingParams.size(); i++) {
- PreviewItemDrawingParams p = mDrawingParams.get(i);
- p.drawable = items.get(i).getCompoundDrawables()[1];
-
- if (p.drawable != null && !mFolder.isOpen()) {
- // Set the callback to FolderIcon as it is responsible to drawing the icon. The
- // callback will be release when the folder is opened.
- p.drawable.setCallback(this);
- }
-
- if (!animate || FeatureFlags.LAUNCHER3_LEGACY_FOLDER_ICON) {
- computePreviewItemDrawingParams(i, nItemsInPreview, p);
- if (mReferenceDrawable == null) {
- mReferenceDrawable = p.drawable;
- }
- } else {
- FolderPreviewItemAnim anim = new FolderPreviewItemAnim(this, p, i, prevNumItems, i,
- nItemsInPreview, DROP_IN_ANIMATION_DURATION, null);
-
- if (p.anim != null) {
- if (p.anim.hasEqualFinalState(anim)) {
- // do nothing, let the current animation finish
- continue;
- }
- p.anim.cancel();
- }
- p.anim = anim;
- p.anim.start();
- }
- }
+ return mPreviewItemManager.verifyDrawable(who) || super.verifyDrawable(who);
}
@Override
public void onItemsChanged(boolean animate) {
- updateItemDrawingParams(animate);
+ mPreviewItemManager.updateItemDrawingParams(animate);
invalidate();
requestLayout();
}
diff --git a/src/com/android/launcher3/folder/FolderPreviewItemAnim.java b/src/com/android/launcher3/folder/FolderPreviewItemAnim.java
index 0da7c5cb1..be075bc9a 100644
--- a/src/com/android/launcher3/folder/FolderPreviewItemAnim.java
+++ b/src/com/android/launcher3/folder/FolderPreviewItemAnim.java
@@ -25,16 +25,16 @@ import com.android.launcher3.LauncherAnimUtils;
* Animates a Folder preview item.
*/
class FolderPreviewItemAnim {
+
+ private static PreviewItemDrawingParams sTmpParams = new PreviewItemDrawingParams(0, 0, 0, 0);
+
private ValueAnimator mValueAnimator;
float finalScale;
float finalTransX;
float finalTransY;
- private PreviewItemDrawingParams mTmpParams = new PreviewItemDrawingParams(0, 0, 0, 0);
-
/**
- * @param folderIcon The FolderIcon this preview will be drawn in.
* @param params layout params to animate
* @param index0 original index of the item to be animated
* @param items0 original number of items in the preview
@@ -43,20 +43,20 @@ class FolderPreviewItemAnim {
* @param duration duration in ms of the animation
* @param onCompleteRunnable runnable to execute upon animation completion
*/
- FolderPreviewItemAnim(final FolderIcon folderIcon, final PreviewItemDrawingParams params,
- int index0, int items0, int index1, int items1, int duration,
- final Runnable onCompleteRunnable) {
- folderIcon.computePreviewItemDrawingParams(index1, items1, mTmpParams);
+ FolderPreviewItemAnim(final PreviewItemManager previewItemManager,
+ final PreviewItemDrawingParams params, int index0, int items0, int index1, int items1,
+ int duration, final Runnable onCompleteRunnable) {
+ previewItemManager.computePreviewItemDrawingParams(index1, items1, sTmpParams);
- finalScale = mTmpParams.scale;
- finalTransX = mTmpParams.transX;
- finalTransY = mTmpParams.transY;
+ finalScale = sTmpParams.scale;
+ finalTransX = sTmpParams.transX;
+ finalTransY = sTmpParams.transY;
- folderIcon.computePreviewItemDrawingParams(index0, items0, mTmpParams);
+ previewItemManager.computePreviewItemDrawingParams(index0, items0, sTmpParams);
- final float scale0 = mTmpParams.scale;
- final float transX0 = mTmpParams.transX;
- final float transY0 = mTmpParams.transY;
+ final float scale0 = sTmpParams.scale;
+ final float transX0 = sTmpParams.transX;
+ final float transY0 = sTmpParams.transY;
mValueAnimator = LauncherAnimUtils.ofFloat(0f, 1.0f);
mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener(){
@@ -66,7 +66,7 @@ class FolderPreviewItemAnim {
params.transX = transX0 + progress * (finalTransX - transX0);
params.transY = transY0 + progress * (finalTransY - transY0);
params.scale = scale0 + progress * (finalScale - scale0);
- folderIcon.invalidate();
+ previewItemManager.onParamsChanged();
}
});
mValueAnimator.addListener(new AnimatorListenerAdapter() {
diff --git a/src/com/android/launcher3/folder/PreviewItemManager.java b/src/com/android/launcher3/folder/PreviewItemManager.java
new file mode 100644
index 000000000..2524a6d82
--- /dev/null
+++ b/src/com/android/launcher3/folder/PreviewItemManager.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+package com.android.launcher3.folder;
+
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.NonNull;
+import android.view.View;
+import android.widget.TextView;
+
+import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.config.FeatureFlags;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.android.launcher3.folder.FolderIcon.DROP_IN_ANIMATION_DURATION;
+
+/**
+ * Manages the drawing and animations of {@link PreviewItemDrawingParams} for a {@link FolderIcon}.
+ */
+public class PreviewItemManager {
+
+ private FolderIcon mIcon;
+
+ // These variables are all associated with the drawing of the preview; they are stored
+ // as member variables for shared usage and to avoid computation on each frame
+ private float mIntrinsicIconSize = -1;
+ private int mTotalWidth = -1;
+ private int mPrevTopPadding = -1;
+ private Drawable mReferenceDrawable = null;
+
+ // These hold the first page preview items
+ private ArrayList<PreviewItemDrawingParams> mFirstPageParams = new ArrayList<>();
+
+ static final int INITIAL_ITEM_ANIMATION_DURATION = 350;
+ private static final int FINAL_ITEM_ANIMATION_DURATION = 200;
+
+ public PreviewItemManager(FolderIcon icon) {
+ mIcon = icon;
+ }
+
+ /**
+ * @param reverse If true, animates the final item in the preview to be full size. If false,
+ * animates the first item to its position in the preview.
+ */
+ public FolderPreviewItemAnim createFirstItemAnimation(final boolean reverse,
+ final Runnable onCompleteRunnable) {
+ return reverse
+ ? new FolderPreviewItemAnim(this, mFirstPageParams.get(0), 0, 2, -1, -1,
+ FINAL_ITEM_ANIMATION_DURATION, onCompleteRunnable)
+ : new FolderPreviewItemAnim(this, mFirstPageParams.get(0), -1, -1, 0, 2,
+ INITIAL_ITEM_ANIMATION_DURATION, onCompleteRunnable);
+ }
+
+ Drawable prepareCreateAnimation(final View destView) {
+ Drawable animateDrawable = ((TextView) destView).getCompoundDrawables()[1];
+ computePreviewDrawingParams(animateDrawable.getIntrinsicWidth(),
+ destView.getMeasuredWidth());
+ mReferenceDrawable = animateDrawable;
+ return animateDrawable;
+ }
+
+ private void computePreviewDrawingParams(Drawable d) {
+ computePreviewDrawingParams(d.getIntrinsicWidth(), mIcon.getMeasuredWidth());
+ }
+
+ private void computePreviewDrawingParams(int drawableSize, int totalSize) {
+ if (mIntrinsicIconSize != drawableSize || mTotalWidth != totalSize ||
+ mPrevTopPadding != mIcon.getPaddingTop()) {
+ mIntrinsicIconSize = drawableSize;
+ mTotalWidth = totalSize;
+ mPrevTopPadding = mIcon.getPaddingTop();
+
+ mIcon.mBackground.setup(mIcon.mLauncher, mIcon, mTotalWidth, mIcon.getPaddingTop());
+ mIcon.mPreviewLayoutRule.init(mIcon.mBackground.previewSize, mIntrinsicIconSize,
+ Utilities.isRtl(mIcon.getResources()));
+
+ updateItemDrawingParams(false);
+ }
+ }
+
+ PreviewItemDrawingParams computePreviewItemDrawingParams(int index, int curNumItems,
+ PreviewItemDrawingParams params) {
+ // We use an index of -1 to represent an icon on the workspace for the destroy and
+ // create animations
+ if (index == -1) {
+ return getFinalIconParams(params);
+ }
+ return mIcon.mPreviewLayoutRule.computePreviewItemDrawingParams(index, curNumItems, params);
+ }
+
+ private PreviewItemDrawingParams getFinalIconParams(PreviewItemDrawingParams params) {
+ float iconSize = mIcon.mLauncher.getDeviceProfile().iconSizePx;
+
+ final float scale = iconSize / mReferenceDrawable.getIntrinsicWidth();
+ final float trans = (mIcon.mBackground.previewSize - iconSize) / 2;
+
+ params.update(trans, trans, scale);
+ return params;
+ }
+
+ public void draw(Canvas canvas) {
+ computePreviewDrawingParams(mReferenceDrawable);
+ // The first item should be drawn last (ie. on top of later items)
+ for (int i = mFirstPageParams.size() - 1; i >= 0; i--) {
+ PreviewItemDrawingParams p = mFirstPageParams.get(i);
+ if (!p.hidden) {
+ drawPreviewItem(canvas, p);
+ }
+ }
+ }
+
+ public void onParamsChanged() {
+ mIcon.invalidate();
+ }
+
+ private void drawPreviewItem(Canvas canvas, PreviewItemDrawingParams params) {
+ canvas.save(Canvas.MATRIX_SAVE_FLAG);
+ canvas.translate(params.transX, params.transY);
+ canvas.scale(params.scale, params.scale);
+ Drawable d = params.drawable;
+
+ if (d != null) {
+ Rect bounds = d.getBounds();
+ canvas.save();
+ canvas.translate(-bounds.left, -bounds.top);
+ canvas.scale(mIntrinsicIconSize / bounds.width(), mIntrinsicIconSize / bounds.height());
+ d.draw(canvas);
+ canvas.restore();
+ }
+ canvas.restore();
+ }
+
+ public void hidePreviewItem(int index, boolean hidden) {
+ PreviewItemDrawingParams params = index < mFirstPageParams.size() ?
+ mFirstPageParams.get(index) : null;
+ if (params != null) {
+ params.hidden = hidden;
+ }
+ }
+
+ void updateItemDrawingParams(boolean animate) {
+ List<BubbleTextView> items = mIcon.getItemsToDisplay();
+ int numItemsInPreview = items.size();
+ int prevNumItems = mFirstPageParams.size();
+
+ // We adjust the size of the list to match the number of items in the preview
+ while (numItemsInPreview < mFirstPageParams.size()) {
+ mFirstPageParams.remove(mFirstPageParams.size() - 1);
+ }
+ while (numItemsInPreview > mFirstPageParams.size()) {
+ mFirstPageParams.add(new PreviewItemDrawingParams(0, 0, 0, 0));
+ }
+
+ for (int i = 0; i < mFirstPageParams.size(); i++) {
+ PreviewItemDrawingParams p = mFirstPageParams.get(i);
+ p.drawable = items.get(i).getCompoundDrawables()[1];
+
+ if (p.drawable != null && !mIcon.mFolder.isOpen()) {
+ // Set the callback to FolderIcon as it is responsible to drawing the icon. The
+ // callback will be released when the folder is opened.
+ p.drawable.setCallback(mIcon);
+ }
+
+ if (!animate || FeatureFlags.LAUNCHER3_LEGACY_FOLDER_ICON) {
+ computePreviewItemDrawingParams(i, numItemsInPreview, p);
+ if (mReferenceDrawable == null) {
+ mReferenceDrawable = p.drawable;
+ }
+ } else {
+ FolderPreviewItemAnim anim = new FolderPreviewItemAnim(this, p, i, prevNumItems, i,
+ numItemsInPreview, DROP_IN_ANIMATION_DURATION, null);
+
+ if (p.anim != null) {
+ if (p.anim.hasEqualFinalState(anim)) {
+ // do nothing, let the current animation finish
+ continue;
+ }
+ p.anim.cancel();
+ }
+ p.anim = anim;
+ p.anim.start();
+ }
+ }
+ }
+
+ boolean verifyDrawable(@NonNull Drawable who) {
+ for (int i = 0; i < mFirstPageParams.size(); i++) {
+ if (mFirstPageParams.get(i).drawable == who) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ float getIntrinsicIconSize() {
+ return mIntrinsicIconSize;
+ }
+}