summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--res/drawable-hdpi/portal_ring_inner.pngbin2340 -> 0 bytes
-rw-r--r--res/drawable-hdpi/portal_ring_inner_nolip.pngbin2231 -> 0 bytes
-rw-r--r--res/drawable-hdpi/portal_ring_outer.pngbin5918 -> 0 bytes
-rw-r--r--res/drawable-hdpi/portal_ring_rest.pngbin1512 -> 0 bytes
-rw-r--r--res/drawable-mdpi/portal_ring_inner.pngbin1431 -> 0 bytes
-rw-r--r--res/drawable-mdpi/portal_ring_inner_nolip.pngbin1382 -> 0 bytes
-rw-r--r--res/drawable-mdpi/portal_ring_outer.pngbin3217 -> 0 bytes
-rw-r--r--res/drawable-mdpi/portal_ring_rest.pngbin871 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/portal_ring_inner.pngbin3275 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/portal_ring_inner_nolip.pngbin3054 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/portal_ring_outer.pngbin8338 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/portal_ring_rest.pngbin2056 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/portal_ring_inner.pngbin5663 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/portal_ring_inner_nolip.pngbin5418 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/portal_ring_outer.pngbin16598 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/portal_ring_rest.pngbin3622 -> 0 bytes
-rw-r--r--res/drawable-xxxhdpi/portal_ring_inner.pngbin7927 -> 0 bytes
-rw-r--r--res/drawable-xxxhdpi/portal_ring_inner_nolip.pngbin7432 -> 0 bytes
-rw-r--r--res/drawable-xxxhdpi/portal_ring_outer.pngbin20634 -> 0 bytes
-rw-r--r--res/drawable-xxxhdpi/portal_ring_rest.pngbin4993 -> 0 bytes
-rw-r--r--res/layout/folder_icon.xml7
-rw-r--r--src/com/android/launcher3/CellLayout.java117
-rw-r--r--src/com/android/launcher3/DeviceProfile.java2
-rw-r--r--src/com/android/launcher3/Launcher.java6
-rw-r--r--src/com/android/launcher3/Workspace.java28
-rw-r--r--src/com/android/launcher3/config/FeatureFlags.java2
-rw-r--r--src/com/android/launcher3/folder/ClippedFolderIconLayoutRule.java16
-rw-r--r--src/com/android/launcher3/folder/FolderIcon.java500
-rw-r--r--src/com/android/launcher3/folder/StackFolderIconLayoutRule.java4
29 files changed, 379 insertions, 303 deletions
diff --git a/res/drawable-hdpi/portal_ring_inner.png b/res/drawable-hdpi/portal_ring_inner.png
deleted file mode 100644
index 65f5af2e7..000000000
--- a/res/drawable-hdpi/portal_ring_inner.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/portal_ring_inner_nolip.png b/res/drawable-hdpi/portal_ring_inner_nolip.png
deleted file mode 100644
index 5be25fc8f..000000000
--- a/res/drawable-hdpi/portal_ring_inner_nolip.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/portal_ring_outer.png b/res/drawable-hdpi/portal_ring_outer.png
deleted file mode 100644
index 712eeb20c..000000000
--- a/res/drawable-hdpi/portal_ring_outer.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/portal_ring_rest.png b/res/drawable-hdpi/portal_ring_rest.png
deleted file mode 100644
index 33cec3218..000000000
--- a/res/drawable-hdpi/portal_ring_rest.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/portal_ring_inner.png b/res/drawable-mdpi/portal_ring_inner.png
deleted file mode 100644
index 7c5e2b744..000000000
--- a/res/drawable-mdpi/portal_ring_inner.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/portal_ring_inner_nolip.png b/res/drawable-mdpi/portal_ring_inner_nolip.png
deleted file mode 100644
index 6ccdebbee..000000000
--- a/res/drawable-mdpi/portal_ring_inner_nolip.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/portal_ring_outer.png b/res/drawable-mdpi/portal_ring_outer.png
deleted file mode 100644
index 40a73abf7..000000000
--- a/res/drawable-mdpi/portal_ring_outer.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/portal_ring_rest.png b/res/drawable-mdpi/portal_ring_rest.png
deleted file mode 100644
index b2c733bdd..000000000
--- a/res/drawable-mdpi/portal_ring_rest.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/portal_ring_inner.png b/res/drawable-xhdpi/portal_ring_inner.png
deleted file mode 100644
index b088042e7..000000000
--- a/res/drawable-xhdpi/portal_ring_inner.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/portal_ring_inner_nolip.png b/res/drawable-xhdpi/portal_ring_inner_nolip.png
deleted file mode 100644
index decf76698..000000000
--- a/res/drawable-xhdpi/portal_ring_inner_nolip.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/portal_ring_outer.png b/res/drawable-xhdpi/portal_ring_outer.png
deleted file mode 100644
index 5ab9a21cf..000000000
--- a/res/drawable-xhdpi/portal_ring_outer.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/portal_ring_rest.png b/res/drawable-xhdpi/portal_ring_rest.png
deleted file mode 100644
index 7d1c84236..000000000
--- a/res/drawable-xhdpi/portal_ring_rest.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/portal_ring_inner.png b/res/drawable-xxhdpi/portal_ring_inner.png
deleted file mode 100644
index cd23cf7ac..000000000
--- a/res/drawable-xxhdpi/portal_ring_inner.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/portal_ring_inner_nolip.png b/res/drawable-xxhdpi/portal_ring_inner_nolip.png
deleted file mode 100644
index d82b910e9..000000000
--- a/res/drawable-xxhdpi/portal_ring_inner_nolip.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/portal_ring_outer.png b/res/drawable-xxhdpi/portal_ring_outer.png
deleted file mode 100644
index e5d33b252..000000000
--- a/res/drawable-xxhdpi/portal_ring_outer.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/portal_ring_rest.png b/res/drawable-xxhdpi/portal_ring_rest.png
deleted file mode 100644
index d52825c21..000000000
--- a/res/drawable-xxhdpi/portal_ring_rest.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxxhdpi/portal_ring_inner.png b/res/drawable-xxxhdpi/portal_ring_inner.png
deleted file mode 100644
index 59e811daa..000000000
--- a/res/drawable-xxxhdpi/portal_ring_inner.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxxhdpi/portal_ring_inner_nolip.png b/res/drawable-xxxhdpi/portal_ring_inner_nolip.png
deleted file mode 100644
index c1e75857e..000000000
--- a/res/drawable-xxxhdpi/portal_ring_inner_nolip.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxxhdpi/portal_ring_outer.png b/res/drawable-xxxhdpi/portal_ring_outer.png
deleted file mode 100644
index f2f818b3b..000000000
--- a/res/drawable-xxxhdpi/portal_ring_outer.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxxhdpi/portal_ring_rest.png b/res/drawable-xxxhdpi/portal_ring_rest.png
deleted file mode 100644
index 2af67b8ee..000000000
--- a/res/drawable-xxxhdpi/portal_ring_rest.png
+++ /dev/null
Binary files differ
diff --git a/res/layout/folder_icon.xml b/res/layout/folder_icon.xml
index b8d5c608b..9eb8c9a67 100644
--- a/res/layout/folder_icon.xml
+++ b/res/layout/folder_icon.xml
@@ -20,13 +20,6 @@
android:layout_height="match_parent"
android:orientation="vertical"
android:focusable="true" >
- <ImageView
- android:id="@+id/preview_background"
- android:layout_gravity="center_horizontal"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:antialias="true"
- android:src="@drawable/portal_ring_inner"/>
<com.android.launcher3.BubbleTextView
style="@style/Icon"
android:id="@+id/folder_icon_name"
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 5832b9f0d..af3703314 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -55,7 +55,6 @@ import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.config.ProviderConfig;
import com.android.launcher3.folder.FolderIcon;
-import com.android.launcher3.folder.FolderIcon.FolderRingAnimator;
import com.android.launcher3.util.ParcelableSparseArray;
import com.android.launcher3.util.Thunk;
@@ -108,8 +107,9 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
private OnTouchListener mInterceptTouchListener;
private StylusEventHelper mStylusEventHelper;
- private ArrayList<FolderRingAnimator> mFolderOuterRings = new ArrayList<FolderRingAnimator>();
- private int[] mFolderLeaveBehindCell = {-1, -1};
+ private ArrayList<FolderIcon.PreviewBackground> mFolderBackgrounds = new ArrayList<FolderIcon.PreviewBackground>();
+ FolderIcon.PreviewBackground mFolderLeaveBehind = new FolderIcon.PreviewBackground();
+ Paint mFolderBgPaint = new Paint();
private float mBackgroundAlpha;
@@ -209,6 +209,9 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
mPreviousReorderDirection[0] = INVALID_DIRECTION;
mPreviousReorderDirection[1] = INVALID_DIRECTION;
+ mFolderLeaveBehind.delegateCellX = -1;
+ mFolderLeaveBehind.delegateCellY = -1;
+
setAlwaysDrawnWithCacheEnabled(false);
final Resources res = getResources();
mHotseatScale = (float) grid.hotseatIconSizePx / grid.iconSizePx;
@@ -501,88 +504,62 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
}
}
- int previewOffset = FolderRingAnimator.sPreviewSize;
-
- // The folder outer / inner ring image(s)
- DeviceProfile grid = mLauncher.getDeviceProfile();
- for (int i = 0; i < mFolderOuterRings.size(); i++) {
- FolderRingAnimator fra = mFolderOuterRings.get(i);
-
- Drawable d;
- int width, height;
- cellToPoint(fra.mCellX, fra.mCellY, mTempLocation);
- View child = getChildAt(fra.mCellX, fra.mCellY);
-
- if (child != null) {
- int centerX = mTempLocation[0] + mCellWidth / 2;
- int centerY = mTempLocation[1] + previewOffset / 2 +
- child.getPaddingTop() + grid.folderBackgroundOffset;
-
- // Draw outer ring, if it exists
- if (FolderIcon.HAS_OUTER_RING) {
- d = FolderRingAnimator.sSharedOuterRingDrawable;
- width = (int) (fra.getOuterRingSize() * getChildrenScale());
- height = width;
- canvas.save();
- canvas.translate(centerX - width / 2, centerY - height / 2);
- d.setBounds(0, 0, width, height);
- d.draw(canvas);
- canvas.restore();
- }
-
- // Draw inner ring
- d = FolderRingAnimator.sSharedInnerRingDrawable;
- width = (int) (fra.getInnerRingSize() * getChildrenScale());
- height = width;
- canvas.save();
- canvas.translate(centerX - width / 2, centerY - width / 2);
- d.setBounds(0, 0, width, height);
- d.draw(canvas);
- canvas.restore();
- }
+ for (int i = 0; i < mFolderBackgrounds.size(); i++) {
+ FolderIcon.PreviewBackground bg = mFolderBackgrounds.get(i);
+ cellToPoint(bg.delegateCellX, bg.delegateCellY, mTempLocation);
+ canvas.save();
+ canvas.translate(mTempLocation[0], mTempLocation[1]);
+ bg.drawBackground(canvas, mFolderBgPaint);
+ canvas.restore();
}
- if (mFolderLeaveBehindCell[0] >= 0 && mFolderLeaveBehindCell[1] >= 0) {
- Drawable d = FolderIcon.sSharedFolderLeaveBehind;
- int width = d.getIntrinsicWidth();
- int height = d.getIntrinsicHeight();
+ if (mFolderLeaveBehind.delegateCellX >= 0 && mFolderLeaveBehind.delegateCellY >= 0) {
+ cellToPoint(mFolderLeaveBehind.delegateCellX,
+ mFolderLeaveBehind.delegateCellY, mTempLocation);
+ canvas.save();
+ canvas.translate(mTempLocation[0], mTempLocation[1]);
+ mFolderLeaveBehind.drawLeaveBehind(canvas, mFolderBgPaint);
+ canvas.restore();
+ }
+ }
- cellToPoint(mFolderLeaveBehindCell[0], mFolderLeaveBehindCell[1], mTempLocation);
- View child = getChildAt(mFolderLeaveBehindCell[0], mFolderLeaveBehindCell[1]);
- if (child != null) {
- int centerX = mTempLocation[0] + mCellWidth / 2;
- int centerY = mTempLocation[1] + previewOffset / 2 +
- child.getPaddingTop() + grid.folderBackgroundOffset;
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ super.dispatchDraw(canvas);
- canvas.save();
- canvas.translate(centerX - width / 2, centerY - width / 2);
- d.setBounds(0, 0, width, height);
- d.draw(canvas);
- canvas.restore();
- }
+ for (int i = 0; i < mFolderBackgrounds.size(); i++) {
+ FolderIcon.PreviewBackground bg = mFolderBackgrounds.get(i);
+ cellToPoint(bg.delegateCellX, bg.delegateCellY, mTempLocation);
+ canvas.save();
+ canvas.translate(mTempLocation[0], mTempLocation[1]);
+ bg.drawBackgroundStroke(canvas, mFolderBgPaint);
+ canvas.restore();
}
}
- public void showFolderAccept(FolderRingAnimator fra) {
- mFolderOuterRings.add(fra);
+ public void addFolderBackground(FolderIcon.PreviewBackground bg) {
+ mFolderBackgrounds.add(bg);
}
-
- public void hideFolderAccept(FolderRingAnimator fra) {
- if (mFolderOuterRings.contains(fra)) {
- mFolderOuterRings.remove(fra);
- }
- invalidate();
+ public void removeFolderBackground(FolderIcon.PreviewBackground bg) {
+ mFolderBackgrounds.remove(bg);
}
public void setFolderLeaveBehindCell(int x, int y) {
- mFolderLeaveBehindCell[0] = x;
- mFolderLeaveBehindCell[1] = y;
+
+ DeviceProfile grid = mLauncher.getDeviceProfile();
+ View child = getChildAt(x, y);
+
+ mFolderLeaveBehind.setup(getResources().getDisplayMetrics(), grid, null,
+ child.getMeasuredWidth(), child.getPaddingTop());
+
+ mFolderLeaveBehind.delegateCellX = x;
+ mFolderLeaveBehind.delegateCellY = y;
invalidate();
}
public void clearFolderLeaveBehind() {
- mFolderLeaveBehindCell[0] = -1;
- mFolderLeaveBehindCell[1] = -1;
+ mFolderLeaveBehind.delegateCellX = -1;
+ mFolderLeaveBehind.delegateCellY = -1;
invalidate();
}
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index b67e07b33..5bfa716ee 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -85,6 +85,7 @@ public class DeviceProfile {
// Folder
public int folderBackgroundOffset;
public int folderIconSizePx;
+ public int folderIconPreviewPadding;
public int folderCellWidthPx;
public int folderCellHeightPx;
@@ -262,6 +263,7 @@ public class DeviceProfile {
folderCellHeightPx = cellHeightPx + edgeMarginPx;
folderBackgroundOffset = -edgeMarginPx;
folderIconSizePx = iconSizePx + 2 * -folderBackgroundOffset;
+ folderIconPreviewPadding = res.getDimensionPixelSize(R.dimen.folder_preview_padding);
}
/**
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 70d982081..2d52341a7 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -3029,13 +3029,17 @@ public class Launcher extends Activity
// We remove and re-draw the FolderIcon in-case it has changed
mDragLayer.removeView(mFolderIconImageView);
copyFolderIconToImage(fi);
+
+ if (cl != null) {
+ cl.clearFolderLeaveBehind();
+ }
+
ObjectAnimator oa = LauncherAnimUtils.ofViewAlphaAndScale(mFolderIconImageView, 1, 1, 1);
oa.setDuration(getResources().getInteger(R.integer.config_folderExpandDuration));
oa.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (cl != null) {
- cl.clearFolderLeaveBehind();
// Remove the ImageView copy of the FolderIcon and make the original visible.
mDragLayer.removeView(mFolderIconImageView);
fi.setVisibility(View.VISIBLE);
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 7bfb7d58f..0f8d834da 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -59,7 +59,6 @@ import android.widget.TextView;
import com.android.launcher3.folder.Folder;
import com.android.launcher3.folder.FolderIcon;
-import com.android.launcher3.folder.FolderIcon.FolderRingAnimator;
import com.android.launcher3.Launcher.CustomContentCallbacks;
import com.android.launcher3.Launcher.LauncherOverlay;
import com.android.launcher3.UninstallDropTarget.UninstallSource;
@@ -224,7 +223,7 @@ public class Workspace extends PagedView
public static final int REORDER_TIMEOUT = 350;
private final Alarm mFolderCreationAlarm = new Alarm();
private final Alarm mReorderAlarm = new Alarm();
- @Thunk FolderRingAnimator mDragFolderRingAnimator = null;
+ private FolderIcon.PreviewBackground mFolderCreateBg = new FolderIcon.PreviewBackground();
private FolderIcon mDragOverFolderIcon = null;
private boolean mCreateUserFolderOnDrop = false;
private boolean mAddToExistingFolderOnDrop = false;
@@ -2493,6 +2492,10 @@ public class Workspace extends PagedView
// If the dragView is null, we can't animate
boolean animate = dragView != null;
if (animate) {
+ // In order to keep everything continuous, we hand off the currently rendered
+ // folder background to the newly created icon. This preserves animation state.
+ fi.setFolderBackground(mFolderCreateBg);
+ mFolderCreateBg = new FolderIcon.PreviewBackground();
fi.performCreateAnimation(destInfo, v, sourceInfo, dragView, folderLocation, scale,
postAnimationRunnable);
} else {
@@ -2855,10 +2858,7 @@ public class Workspace extends PagedView
}
private void cleanupFolderCreation() {
- if (mDragFolderRingAnimator != null) {
- mDragFolderRingAnimator.animateToNaturalState();
- mDragFolderRingAnimator = null;
- }
+ mFolderCreateBg.animateToRest();
mFolderCreationAlarm.setOnAlarmListener(null);
mFolderCreationAlarm.cancelAlarm();
}
@@ -3166,18 +3166,16 @@ public class Workspace extends PagedView
this.layout = layout;
this.cellX = cellX;
this.cellY = cellY;
+
+ DeviceProfile grid = mLauncher.getDeviceProfile();
+ BubbleTextView cell = (BubbleTextView) layout.getChildAt(cellX, cellY);
+
+ mFolderCreateBg.setup(getResources().getDisplayMetrics(), grid, null,
+ cell.getMeasuredWidth(), cell.getPaddingTop());
}
public void onAlarm(Alarm alarm) {
- if (mDragFolderRingAnimator != null) {
- // This shouldn't happen ever, but just in case, make sure we clean up the mess.
- mDragFolderRingAnimator.animateToNaturalState();
- }
- mDragFolderRingAnimator = new FolderRingAnimator(mLauncher, null);
- mDragFolderRingAnimator.setCell(cellX, cellY);
- mDragFolderRingAnimator.setCellLayout(layout);
- mDragFolderRingAnimator.animateToAcceptState();
- layout.showFolderAccept(mDragFolderRingAnimator);
+ mFolderCreateBg.animateToAccept(layout, cellX, cellY);
layout.clearDragOutlines();
setDragMode(DRAG_MODE_CREATE_FOLDER);
}
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 285f2c1df..2b3727a8a 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -34,7 +34,7 @@ public final class FeatureFlags {
// As opposed to the new spring-loaded workspace.
public static boolean LAUNCHER3_LEGACY_WORKSPACE_DND = false;
public static boolean LAUNCHER3_ICON_NORMALIZATION = true;
- public static boolean LAUNCHER3_CLIPPED_FOLDER_ICON = false;
+ public static boolean LAUNCHER3_LEGACY_FOLDER_ICON = false;
public static boolean LAUNCHER3_LEGACY_LOGGING = false;
public static boolean LAUNCHER3_USE_SYSTEM_DRAG_DRIVER = false;
}
diff --git a/src/com/android/launcher3/folder/ClippedFolderIconLayoutRule.java b/src/com/android/launcher3/folder/ClippedFolderIconLayoutRule.java
index 48988d7f2..68b756b24 100644
--- a/src/com/android/launcher3/folder/ClippedFolderIconLayoutRule.java
+++ b/src/com/android/launcher3/folder/ClippedFolderIconLayoutRule.java
@@ -15,6 +15,7 @@ public class ClippedFolderIconLayoutRule implements FolderIcon.PreviewLayoutRule
final float MIN_SCALE = 0.48f;
final float MAX_SCALE = 0.58f;
final float MAX_RADIUS_DILATION = 0.15f;
+ final float ITEM_RADIUS_SCALE_FACTOR = 1.33f;
private float[] mTmpPoint = new float[2];
@@ -22,27 +23,19 @@ public class ClippedFolderIconLayoutRule implements FolderIcon.PreviewLayoutRule
private float mRadius;
private float mIconSize;
private boolean mIsRtl;
- private Path mClipPath = new Path();
@Override
public void init(int availableSpace, int intrinsicIconSize, boolean rtl) {
mAvailableSpace = availableSpace;
- mRadius = 0.66f * availableSpace;
+ mRadius = ITEM_RADIUS_SCALE_FACTOR * availableSpace / 2f;
mIconSize = intrinsicIconSize;
mIsRtl = rtl;
-
- // We make the clip radius just slightly smaller than the background drawable
- // TODO(adamcohen): this is hacky, needs cleanup (likely through programmatic drawing).
- int clipRadius = (int) mAvailableSpace / 2 - 1;
-
- mClipPath.addCircle(mAvailableSpace / 2, mAvailableSpace / 2, clipRadius, Path.Direction.CW);
}
@Override
public FolderIcon.PreviewItemDrawingParams computePreviewItemDrawingParams(int index,
int curNumItems, FolderIcon.PreviewItemDrawingParams params) {
-
float totalScale = scaleForNumItems(curNumItems);
float transX;
float transY;
@@ -55,7 +48,6 @@ public class ClippedFolderIconLayoutRule implements FolderIcon.PreviewLayoutRule
getPosition(index, curNumItems, mTmpPoint);
transX = mTmpPoint[0];
transY = mTmpPoint[1];
- totalScale = scaleForNumItems(curNumItems);
}
if (params == null) {
@@ -126,8 +118,8 @@ public class ClippedFolderIconLayoutRule implements FolderIcon.PreviewLayoutRule
}
@Override
- public Path getClipPath() {
- return mClipPath;
+ public boolean clipToBackground() {
+ return true;
}
}
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index 7b71a36d1..62007f072 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -21,16 +21,17 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
-import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.Rect;
+import android.graphics.Region;
import android.graphics.drawable.Drawable;
-import android.os.Looper;
import android.os.Parcelable;
import android.util.AttributeSet;
+import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
@@ -39,7 +40,6 @@ import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
-import android.widget.ImageView;
import android.widget.TextView;
import com.android.launcher3.Alarm;
@@ -77,15 +77,14 @@ import java.util.ArrayList;
* An icon that can appear on in the workspace representing an {@link Folder}.
*/
public class FolderIcon extends FrameLayout implements FolderListener {
- @Thunk
- Launcher mLauncher;
+ @Thunk Launcher mLauncher;
@Thunk Folder mFolder;
private FolderInfo mInfo;
@Thunk static boolean sStaticValuesDirty = true;
- public static final int NUM_ITEMS_IN_PREVIEW = FeatureFlags.LAUNCHER3_CLIPPED_FOLDER_ICON ?
- ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW :
- StackFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW;
+ public static final int NUM_ITEMS_IN_PREVIEW = FeatureFlags.LAUNCHER3_LEGACY_FOLDER_ICON ?
+ StackFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW :
+ ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW;
private CheckLongPressHelper mLongPressHelper;
private StylusEventHelper mStylusEventHelper;
@@ -96,36 +95,19 @@ public class FolderIcon extends FrameLayout implements FolderListener {
private static final int INITIAL_ITEM_ANIMATION_DURATION = 350;
private static final int FINAL_ITEM_ANIMATION_DURATION = 200;
- // The degree to which the inner ring grows when accepting drop
- private static final float INNER_RING_GROWTH_FACTOR = 0.15f;
-
- // The degree to which the outer ring is scaled in its natural state
- private static final float OUTER_RING_GROWTH_FACTOR = 0.3f;
-
- // Flag as to whether or not to draw an outer ring. Currently none is designed.
- public static final boolean HAS_OUTER_RING = true;
-
// Flag whether the folder should open itself when an item is dragged over is enabled.
public static final boolean SPRING_LOADING_ENABLED = true;
// Delay when drag enters until the folder opens, in miliseconds.
private static final int ON_OPEN_DELAY = 800;
- public static Drawable sSharedFolderLeaveBehind = null;
-
- @Thunk ImageView mPreviewBackground;
- @Thunk
- BubbleTextView mFolderName;
-
- FolderRingAnimator mFolderRingAnimator = null;
+ @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 int mIntrinsicIconSize;
- private int mAvailableSpaceInPreview;
- private int mPreviewOffsetX;
- private int mPreviewOffsetY;
private int mTotalWidth;
+ PreviewBackground mBackground = new PreviewBackground();
private PreviewLayoutRule mPreviewLayoutRule;
@@ -138,6 +120,8 @@ public class FolderIcon extends FrameLayout implements FolderListener {
private ArrayList<PreviewItemDrawingParams> mDrawingParams = new ArrayList<PreviewItemDrawingParams>();
private Drawable mReferenceDrawable = null;
+ Paint mBgPaint = new Paint();
+
private Alarm mOpenAlarm = new Alarm();
@Thunk
ItemInfo mDragInfo;
@@ -155,17 +139,11 @@ public class FolderIcon extends FrameLayout implements FolderListener {
private void init() {
mLongPressHelper = new CheckLongPressHelper(this);
mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this);
- mPreviewLayoutRule = FeatureFlags.LAUNCHER3_CLIPPED_FOLDER_ICON ?
- new ClippedFolderIconLayoutRule() :
- new StackFolderIconLayoutRule();
- setAccessibilityDelegate(LauncherAppState.getInstance().getAccessibilityDelegate());
- }
+ mPreviewLayoutRule = FeatureFlags.LAUNCHER3_LEGACY_FOLDER_ICON ?
+ new StackFolderIconLayoutRule() :
+ new ClippedFolderIconLayoutRule();
- public boolean isDropEnabled() {
- final ViewGroup cellLayoutChildren = (ViewGroup) getParent();
- final ViewGroup cellLayout = (ViewGroup) cellLayoutChildren.getParent();
- final Workspace workspace = (Workspace) cellLayout.getParent();
- return !workspace.workspaceInModalState();
+ setAccessibilityDelegate(LauncherAppState.getInstance().getAccessibilityDelegate());
}
public static FolderIcon fromXml(int resId, Launcher launcher, ViewGroup group,
@@ -179,8 +157,13 @@ public class FolderIcon extends FrameLayout implements FolderListener {
}
DeviceProfile grid = launcher.getDeviceProfile();
-
FolderIcon icon = (FolderIcon) LayoutInflater.from(launcher).inflate(resId, group, false);
+
+ // For performance and compatibility reasons we render the preview using a software layer.
+ // In particular, hardware path clipping has spotty ecosystem support and bad performance.
+ // Software rendering also allows us to use shadow layers.
+ icon.setLayerType(LAYER_TYPE_SOFTWARE, new Paint(Paint.FILTER_BITMAP_FLAG));
+
icon.setClipToPadding(false);
icon.mFolderName = (BubbleTextView) icon.findViewById(R.id.folder_icon_name);
icon.mFolderName.setText(folderInfo.title);
@@ -188,13 +171,6 @@ public class FolderIcon extends FrameLayout implements FolderListener {
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) icon.mFolderName.getLayoutParams();
lp.topMargin = grid.iconSizePx + grid.iconDrawablePaddingPx;
- // Offset the preview background to center this view accordingly
- icon.mPreviewBackground = (ImageView) icon.findViewById(R.id.preview_background);
- lp = (FrameLayout.LayoutParams) icon.mPreviewBackground.getLayoutParams();
- lp.topMargin = grid.folderBackgroundOffset;
- lp.width = grid.folderIconSizePx;
- lp.height = grid.folderIconSizePx;
-
icon.setTag(folderInfo);
icon.setOnClickListener(launcher);
icon.mInfo = folderInfo;
@@ -206,7 +182,6 @@ public class FolderIcon extends FrameLayout implements FolderListener {
folder.bind(folderInfo);
icon.setFolder(folder);
- icon.mFolderRingAnimator = new FolderRingAnimator(launcher, icon);
folderInfo.addListener(icon);
icon.setOnFocusChangeListener(launcher.mFocusHandler);
@@ -219,129 +194,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
return super.onSaveInstanceState();
}
- public static class FolderRingAnimator {
- public int mCellX;
- public int mCellY;
- @Thunk
- CellLayout mCellLayout;
- public float mOuterRingSize;
- public float mInnerRingSize;
- public FolderIcon mFolderIcon = null;
- public static Drawable sSharedOuterRingDrawable = null;
- public static Drawable sSharedInnerRingDrawable = null;
- public static int sPreviewSize = -1;
- public static int sPreviewPadding = -1;
-
- private ValueAnimator mAcceptAnimator;
- private ValueAnimator mNeutralAnimator;
-
- public FolderRingAnimator(Launcher launcher, FolderIcon folderIcon) {
- mFolderIcon = folderIcon;
- Resources res = launcher.getResources();
-
- // We need to reload the static values when configuration changes in case they are
- // different in another configuration
- if (sStaticValuesDirty) {
- if (Looper.myLooper() != Looper.getMainLooper()) {
- throw new RuntimeException("FolderRingAnimator loading drawables on non-UI thread "
- + Thread.currentThread());
- }
-
- DeviceProfile grid = launcher.getDeviceProfile();
- sPreviewSize = grid.folderIconSizePx;
- sPreviewPadding = res.getDimensionPixelSize(R.dimen.folder_preview_padding);
- sSharedOuterRingDrawable = res.getDrawable(R.drawable.portal_ring_outer);
- sSharedInnerRingDrawable = res.getDrawable(R.drawable.portal_ring_inner_nolip);
- sSharedFolderLeaveBehind = res.getDrawable(R.drawable.portal_ring_rest);
- sStaticValuesDirty = false;
- }
- }
-
- public void animateToAcceptState() {
- if (mNeutralAnimator != null) {
- mNeutralAnimator.cancel();
- }
- mAcceptAnimator = LauncherAnimUtils.ofFloat(mCellLayout, 0f, 1f);
- mAcceptAnimator.setDuration(CONSUMPTION_ANIMATION_DURATION);
-
- final int previewSize = sPreviewSize;
- mAcceptAnimator.addUpdateListener(new AnimatorUpdateListener() {
- public void onAnimationUpdate(ValueAnimator animation) {
- final float percent = animation.getAnimatedFraction();
- mOuterRingSize = (1 + percent * OUTER_RING_GROWTH_FACTOR) * previewSize;
- mInnerRingSize = (1 + percent * INNER_RING_GROWTH_FACTOR) * previewSize;
- if (mCellLayout != null) {
- mCellLayout.invalidate();
- }
- }
- });
- mAcceptAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- if (mFolderIcon != null) {
- mFolderIcon.mPreviewBackground.setVisibility(INVISIBLE);
- }
- }
- });
- mAcceptAnimator.start();
- }
-
- public void animateToNaturalState() {
- if (mAcceptAnimator != null) {
- mAcceptAnimator.cancel();
- }
- mNeutralAnimator = LauncherAnimUtils.ofFloat(mCellLayout, 0f, 1f);
- mNeutralAnimator.setDuration(CONSUMPTION_ANIMATION_DURATION);
-
- final int previewSize = sPreviewSize;
- mNeutralAnimator.addUpdateListener(new AnimatorUpdateListener() {
- public void onAnimationUpdate(ValueAnimator animation) {
- final float percent = (Float) animation.getAnimatedValue();
- mOuterRingSize = (1 + (1 - percent) * OUTER_RING_GROWTH_FACTOR) * previewSize;
- mInnerRingSize = (1 + (1 - percent) * INNER_RING_GROWTH_FACTOR) * previewSize;
- if (mCellLayout != null) {
- mCellLayout.invalidate();
- }
- }
- });
- mNeutralAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- if (mCellLayout != null) {
- mCellLayout.hideFolderAccept(FolderRingAnimator.this);
- }
- if (mFolderIcon != null) {
- mFolderIcon.mPreviewBackground.setVisibility(VISIBLE);
- }
- }
- });
- mNeutralAnimator.start();
- }
-
- // Location is expressed in window coordinates
- public void getCell(int[] loc) {
- loc[0] = mCellX;
- loc[1] = mCellY;
- }
-
- // Location is expressed in window coordinates
- public void setCell(int x, int y) {
- mCellX = x;
- mCellY = y;
- }
- public void setCellLayout(CellLayout layout) {
- mCellLayout = layout;
- }
-
- public float getOuterRingSize() {
- return mOuterRingSize;
- }
-
- public float getInnerRingSize() {
- return mInnerRingSize;
- }
- }
public Folder getFolder() {
return mFolder;
@@ -375,11 +228,9 @@ public class FolderIcon extends FrameLayout implements FolderListener {
public void onDragEnter(ItemInfo dragInfo) {
if (mFolder.isDestroyed() || !willAcceptItem(dragInfo)) return;
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
- CellLayout layout = (CellLayout) getParent().getParent();
- mFolderRingAnimator.setCell(lp.cellX, lp.cellY);
- mFolderRingAnimator.setCellLayout(layout);
- mFolderRingAnimator.animateToAcceptState();
- layout.showFolderAccept(mFolderRingAnimator);
+ CellLayout cl = (CellLayout) getParent().getParent();
+
+ mBackground.animateToAccept(cl, lp.cellX, lp.cellY);
mOpenAlarm.setOnAlarmListener(mOnOpenListener);
if (SPRING_LOADING_ENABLED &&
((dragInfo instanceof AppInfo) || (dragInfo instanceof ShortcutInfo))) {
@@ -445,7 +296,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
}
public void onDragExit() {
- mFolderRingAnimator.animateToNaturalState();
+ mBackground.animateToRest();
mOpenAlarm.cancelAlarm();
}
@@ -531,16 +382,11 @@ public class FolderIcon extends FrameLayout implements FolderListener {
mIntrinsicIconSize = drawableSize;
mTotalWidth = totalSize;
- final int previewSize = FolderRingAnimator.sPreviewSize;
- final int previewPadding = FolderRingAnimator.sPreviewPadding;
-
- mAvailableSpaceInPreview = (previewSize - 2 * previewPadding);
-
- mPreviewOffsetX = (mTotalWidth - mAvailableSpaceInPreview) / 2;
- mPreviewOffsetY = previewPadding + grid.folderBackgroundOffset + getPaddingTop();
-
- mPreviewLayoutRule.init(mAvailableSpaceInPreview, mIntrinsicIconSize,
+ mBackground.setup(getResources().getDisplayMetrics(), grid, this, mTotalWidth,
+ getPaddingTop());
+ mPreviewLayoutRule.init(mBackground.previewSize, mIntrinsicIconSize,
Utilities.isRtl(getResources()));
+
updateItemDrawingParams(false);
}
}
@@ -586,8 +432,8 @@ public class FolderIcon extends FrameLayout implements FolderListener {
mTmpParams = computePreviewItemDrawingParams(Math.min(mPreviewLayoutRule.numItems(), index),
curNumItems, mTmpParams);
- mTmpParams.transX += mPreviewOffsetX;
- mTmpParams.transY += mPreviewOffsetY;
+ mTmpParams.transX += mBackground.basePreviewOffsetX;
+ mTmpParams.transY += mBackground.basePreviewOffsetY;
float offsetX = mTmpParams.transX + (mTmpParams.scale * mIntrinsicIconSize) / 2;
float offsetY = mTmpParams.transY + (mTmpParams.scale * mIntrinsicIconSize) / 2;
@@ -610,7 +456,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
float iconSize = mLauncher.getDeviceProfile().iconSizePx;
final float scale = iconSize / mReferenceDrawable.getIntrinsicWidth();
- final float trans = (mAvailableSpaceInPreview - iconSize) / 2;
+ final float trans = (mBackground.previewSize - iconSize) / 2;
params.update(trans, trans, scale);
return params;
@@ -642,24 +488,284 @@ public class FolderIcon extends FrameLayout implements FolderListener {
canvas.restore();
}
+ public static class PreviewBackground {
+ private float mScale = 1f;
+ private float mColorMultiplier = 1f;
+ private Path mClipPath = new Path();
+ private int mStrokeWidth;
+ private View mInvalidateDeligate;
+
+ public int previewSize;
+ private int basePreviewOffsetX;
+ private int basePreviewOffsetY;
+
+ private CellLayout mDrawingDelegate;
+ public int delegateCellX;
+ public int delegateCellY;
+
+ // Drawing / animation configurations
+ private static final float ACCEPT_SCALE_FACTOR = 1.25f;
+ private static final float ACCEPT_COLOR_MULTIPLIER = 1.5f;
+
+ // Expressed on a scale from 0 to 255.
+ private static final int BG_OPACITY = 160;
+ private static final int MAX_BG_OPACITY = 225;
+ private static final int BG_INTENSITY = 245;
+ private static final int SHADOW_OPACITY = 80;
+
+ ValueAnimator mScaleAnimator;
+
+ public void setup(DisplayMetrics dm, DeviceProfile grid, View invalidateDeligate,
+ int availableSpace, int topPadding) {
+ mInvalidateDeligate = invalidateDeligate;
+
+ final int previewSize = grid.folderIconSizePx;
+ final int previewPadding = grid.folderIconPreviewPadding;
+
+ this.previewSize = (previewSize - 2 * previewPadding);
+
+ basePreviewOffsetX = (availableSpace - this.previewSize) / 2;
+ basePreviewOffsetY = previewPadding + grid.folderBackgroundOffset + topPadding;
+
+ mStrokeWidth = Utilities.pxFromDp(1, dm);
+
+ invalidate();
+ }
+
+ int getRadius() {
+ return previewSize / 2;
+ }
+
+ int getScaledRadius() {
+ return (int) (mScale * getRadius());
+ }
+
+ int getOffsetX() {
+ return basePreviewOffsetX - (getScaledRadius() - getRadius());
+ }
+
+ int getOffsetY() {
+ return basePreviewOffsetY - (getScaledRadius() - getRadius());
+ }
+
+ void invalidate() {
+ int radius = getScaledRadius();
+ mClipPath.reset();
+ mClipPath.addCircle(radius, radius, radius, Path.Direction.CW);
+
+ if (mInvalidateDeligate != null) {
+ mInvalidateDeligate.invalidate();
+ }
+
+ if (mDrawingDelegate != null) {
+ mDrawingDelegate.invalidate();
+ }
+ }
+
+ void setInvalidateDeligate(View invalidateDeligate) {
+ mInvalidateDeligate = invalidateDeligate;
+ invalidate();
+ }
+
+ public void drawBackground(Canvas canvas, Paint paint) {
+ canvas.save();
+ canvas.translate(getOffsetX(), getOffsetY());
+
+ paint.reset();
+ paint.setStyle(Paint.Style.FILL);
+ paint.setXfermode(null);
+ paint.setAntiAlias(true);
+
+ int alpha = (int) Math.min(MAX_BG_OPACITY, BG_OPACITY * mColorMultiplier);
+ paint.setColor(Color.argb(alpha, BG_INTENSITY, BG_INTENSITY, BG_INTENSITY));
+
+ float radius = getScaledRadius();
+
+ canvas.drawCircle(radius, radius, radius, paint);
+ canvas.clipPath(mClipPath, Region.Op.DIFFERENCE);
+
+ paint.setStyle(Paint.Style.STROKE);
+ paint.setColor(Color.TRANSPARENT);
+ paint.setShadowLayer(mStrokeWidth, 0, mStrokeWidth, Color.argb(SHADOW_OPACITY, 0, 0, 0));
+ canvas.drawCircle(radius, radius, radius, paint);
+
+ canvas.restore();
+ }
+
+ public void drawBackgroundStroke(Canvas canvas, Paint paint) {
+ canvas.save();
+ canvas.translate(getOffsetX(), getOffsetY());
+
+ paint.reset();
+ paint.setAntiAlias(true);
+ paint.setColor(Color.argb(255, BG_INTENSITY, BG_INTENSITY, BG_INTENSITY));
+ paint.setStyle(Paint.Style.STROKE);
+ paint.setStrokeWidth(mStrokeWidth);
+
+ float radius = getScaledRadius();
+ canvas.drawCircle(radius, radius, radius - 1, paint);
+
+ canvas.restore();
+ }
+
+ public void drawLeaveBehind(Canvas canvas, Paint paint) {
+ float originalScale = mScale;
+ mScale = 0.5f;
+
+ canvas.save();
+ canvas.translate(getOffsetX(), getOffsetY());
+
+ paint.reset();
+ paint.setAntiAlias(true);
+ paint.setColor(Color.argb(160, 245, 245, 245));
+
+ float radius = getScaledRadius();
+ canvas.drawCircle(radius, radius, radius, paint);
+
+ canvas.restore();
+ mScale = originalScale;
+ }
+
+ // It is the callers responsibility to save and restore the canvas.
+ private void clipCanvas(Canvas canvas) {
+ canvas.translate(getOffsetX(), getOffsetY());
+ canvas.clipPath(mClipPath);
+ canvas.translate(-getOffsetX(), -getOffsetY());
+ }
+
+ private void delegateDrawing(CellLayout delegate, int cellX, int cellY) {
+ if (mDrawingDelegate != delegate) {
+ delegate.addFolderBackground(this);
+ }
+
+ mDrawingDelegate = delegate;
+ delegateCellX = cellX;
+ delegateCellY = cellY;
+
+ invalidate();
+ }
+
+ private void clearDrawingDelegate() {
+ if (mDrawingDelegate != null) {
+ mDrawingDelegate.removeFolderBackground(this);
+ }
+
+ mDrawingDelegate = null;
+ invalidate();
+ }
+
+ private boolean drawingDelegated() {
+ return mDrawingDelegate != null;
+ }
+
+ private void animateScale(float finalScale, float finalMultiplier,
+ final Runnable onStart, final Runnable onEnd) {
+ final float scale0 = mScale;
+ final float scale1 = finalScale;
+
+ final float bgMultiplier0 = mColorMultiplier;
+ final float bgMultiplier1 = finalMultiplier;
+
+ if (mScaleAnimator != null) {
+ mScaleAnimator.cancel();
+ }
+
+ mScaleAnimator = LauncherAnimUtils.ofFloat(null, 0f, 1.0f);
+
+ mScaleAnimator.addUpdateListener(new AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ float prog = animation.getAnimatedFraction();
+ mScale = prog * scale1 + (1 - prog) * scale0;
+ mColorMultiplier = prog * bgMultiplier1 + (1 - prog) * bgMultiplier0;
+ invalidate();
+ }
+ });
+ mScaleAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ if (onStart != null) {
+ onStart.run();
+ }
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (onEnd != null) {
+ onEnd.run();
+ }
+ mScaleAnimator = null;
+ }
+ });
+
+ mScaleAnimator.setDuration(CONSUMPTION_ANIMATION_DURATION);
+ mScaleAnimator.start();
+ }
+
+ public void animateToAccept(final CellLayout cl, final int cellX, final int cellY) {
+ Runnable onStart = new Runnable() {
+ @Override
+ public void run() {
+ delegateDrawing(cl, cellX, cellY);
+ }
+ };
+ animateScale(ACCEPT_SCALE_FACTOR, ACCEPT_COLOR_MULTIPLIER, onStart, null);
+ }
+
+ public void animateToRest() {
+ // This can be called multiple times -- we need to make sure the drawing delegate
+ // is saved and restored at the beginning of the animation, since cancelling the
+ // existing animation can clear the delgate.
+ final CellLayout cl = mDrawingDelegate;
+ final int cellX = delegateCellX;
+ final int cellY = delegateCellY;
+
+ Runnable onStart = new Runnable() {
+ @Override
+ public void run() {
+ delegateDrawing(cl, cellX, cellY);
+ }
+ };
+ Runnable onEnd = new Runnable() {
+ @Override
+ public void run() {
+ clearDrawingDelegate();
+ }
+ };
+ animateScale(1f, 1f, onStart, onEnd);
+ }
+ }
+
+ public void setFolderBackground(PreviewBackground bg) {
+ mBackground = bg;
+ mBackground.setInvalidateDeligate(this);
+ }
+
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
- if (mFolder == null) return;
- if (mFolder.getItemCount() == 0 && !mAnimating) return;
-
if (mReferenceDrawable != null) {
computePreviewDrawingParams(mReferenceDrawable);
}
+ if (!mBackground.drawingDelegated()) {
+ mBackground.drawBackground(canvas, mBgPaint);
+ }
+
+ if (mFolder == null) return;
+ if (mFolder.getItemCount() == 0 && !mAnimating) return;
+
canvas.save();
- canvas.translate(mPreviewOffsetX, mPreviewOffsetY);
- Path clipPath = mPreviewLayoutRule.getClipPath();
- if (clipPath != null) {
- canvas.clipPath(clipPath);
+
+
+ if (mPreviewLayoutRule.clipToBackground()) {
+ mBackground.clipCanvas(canvas);
}
+ // 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);
@@ -668,6 +774,10 @@ public class FolderIcon extends FrameLayout implements FolderListener {
}
}
canvas.restore();
+
+ if (mPreviewLayoutRule.clipToBackground() && !mBackground.drawingDelegated()) {
+ mBackground.drawBackgroundStroke(canvas, mBgPaint);
+ }
}
private Drawable getTopDrawable(TextView v) {
@@ -793,7 +903,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
PreviewItemDrawingParams p = mDrawingParams.get(i);
p.drawable = getTopDrawable((TextView) items.get(i));
- if (!animate || !FeatureFlags.LAUNCHER3_CLIPPED_FOLDER_ICON) {
+ if (!animate || FeatureFlags.LAUNCHER3_LEGACY_FOLDER_ICON) {
computePreviewItemDrawingParams(i, nItemsInPreview, p);
if (mReferenceDrawable == null) {
mReferenceDrawable = p.drawable;
@@ -884,6 +994,6 @@ public class FolderIcon extends FrameLayout implements FolderListener {
public void init(int availableSpace, int intrinsicIconSize, boolean rtl);
public int numItems();
- public Path getClipPath();
+ public boolean clipToBackground();
}
}
diff --git a/src/com/android/launcher3/folder/StackFolderIconLayoutRule.java b/src/com/android/launcher3/folder/StackFolderIconLayoutRule.java
index 005307209..7fb02e313 100644
--- a/src/com/android/launcher3/folder/StackFolderIconLayoutRule.java
+++ b/src/com/android/launcher3/folder/StackFolderIconLayoutRule.java
@@ -85,7 +85,7 @@ public class StackFolderIconLayoutRule implements FolderIcon.PreviewLayoutRule {
}
@Override
- public Path getClipPath() {
- return null;
+ public boolean clipToBackground() {
+ return false;
}
}