Merge "Set mDragInProcess to false in onDragEnd." into ub-launcher3-dorval-polish
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index b84c627..7bf6651 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -621,6 +621,10 @@
return result;
}
+ public AppInfo findApp(ComponentKey key) {
+ return mComponentToAppMap.get(key);
+ }
+
/**
* Returns the cached section name for the given title, recomputing and updating the cache if
* the title has no cached section name.
diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java
index 9c6b956..0418d25 100644
--- a/src/com/android/launcher3/dragndrop/DragView.java
+++ b/src/com/android/launcher3/dragndrop/DragView.java
@@ -16,15 +16,19 @@
package com.android.launcher3.dragndrop;
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.FloatArrayEvaluator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.annotation.SuppressLint;
-import android.content.pm.PackageManager;
+import android.annotation.TargetApi;
+import android.content.pm.LauncherActivityInfo;
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Matrix;
@@ -33,7 +37,10 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.AdaptiveIconDrawable;
+import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.InsetDrawable;
+import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.support.animation.DynamicAnimation;
@@ -44,20 +51,29 @@
import android.widget.FrameLayout;
import android.widget.ImageView;
+import com.android.launcher3.FastBitmapDrawable;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAnimUtils;
+import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.compat.LauncherAppsCompat;
+import com.android.launcher3.compat.ShortcutConfigActivityInfo;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.graphics.IconNormalizer;
+import com.android.launcher3.graphics.LauncherIcons;
+import com.android.launcher3.shortcuts.DeepShortcutManager;
+import com.android.launcher3.shortcuts.ShortcutInfoCompat;
+import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.util.Themes;
import com.android.launcher3.util.Thunk;
+import com.android.launcher3.widget.PendingAddShortcutInfo;
import java.util.Arrays;
-
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import java.util.List;
public class DragView extends FrameLayout {
public static final int COLOR_CHANGE_DURATION = 120;
@@ -100,9 +116,7 @@
private SpringAnimation mSpringX, mSpringY;
private ImageView mFgImageView, mBgImageView;
private Path mScaledMaskPath;
- // TODO: figure out if there is smarter way to retrieve these two constants below
- private final static float ADAPTIVE_ICON_SCALE = .731121626f;
- private final static float ADAPTIVE_ICON_MASK_SCALE = 1.165f; //1.185f;
+ private Drawable mBadge;
// Following three values are fine tuned with motion ux designer
private final static int STIFFNESS = 4000;
@@ -185,12 +199,13 @@
/**
* Initialize {@code #mIconDrawable} only if the icon type is app icon (not shortcut or folder).
*/
+ @TargetApi(Build.VERSION_CODES.O)
public void setItemInfo(final ItemInfo info) {
if (!(FeatureFlags.LAUNCHER3_SPRING_ICONS && Utilities.isAtLeastO())) {
return;
}
- if (!(info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
- || info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT)) {
+ if (info.itemType != LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
+ info.itemType != LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
return;
}
// Load the adaptive icon on a background thread and add the view in ui thread.
@@ -198,40 +213,114 @@
new Handler(workerLooper).postAtFrontOfQueue(new Runnable() {
@Override
public void run() {
- PackageManager pm = (mLauncher).getPackageManager();
- try {
- Drawable dr = pm.getActivityIcon(info.getTargetComponent());
- if (dr instanceof AdaptiveIconDrawable) {
- int w = mBitmap.getWidth();
- int h = mBitmap.getHeight();
- AdaptiveIconDrawable adaptiveIcon = (AdaptiveIconDrawable) dr;
- adaptiveIcon.setBounds(0, 0, w, h);
- setupMaskPath(adaptiveIcon);
- mFgImageView = setupImageView(adaptiveIcon.getForeground());
- mBgImageView = setupImageView(adaptiveIcon.getBackground());
- mSpringX = setupSpringAnimation(-w/4, w/4, DynamicAnimation.TRANSLATION_X);
- mSpringY = setupSpringAnimation(-h/4, h/4, DynamicAnimation.TRANSLATION_Y);
+ LauncherAppState appState = LauncherAppState.getInstance(mLauncher);
+ Object[] outObj = new Object[1];
+ Drawable dr = getFullDrawable(info, appState, outObj);
- new Handler(Looper.getMainLooper()).post(new Runnable() {
- @Override
- public void run() {
- addView(mBgImageView);
- addView(mFgImageView);
- setWillNotDraw(true);
- }
- });
- }
- } catch (PackageManager.NameNotFoundException e) { }
+ if (dr instanceof AdaptiveIconDrawable) {
+ int w = mBitmap.getWidth();
+ int h = mBitmap.getHeight();
+ AdaptiveIconDrawable adaptiveIcon = (AdaptiveIconDrawable) dr;
+ adaptiveIcon.setBounds(0, 0, w, h);
+ float blurSizeOutline = mLauncher.getResources()
+ .getDimension(R.dimen.blur_size_medium_outline);
+ float normalizationScale = IconNormalizer.getInstance(mLauncher)
+ .getScale(adaptiveIcon, null, null, null) * ((w - blurSizeOutline) / w);
+
+ final Path mask = getMaskPath(adaptiveIcon, normalizationScale);
+ mFgImageView = setupImageView(adaptiveIcon.getForeground(), normalizationScale);
+ mBgImageView = setupImageView(adaptiveIcon.getBackground(), normalizationScale);
+ mSpringX = setupSpringAnimation(-w/4, w/4, DynamicAnimation.TRANSLATION_X);
+ mSpringY = setupSpringAnimation(-h/4, h/4, DynamicAnimation.TRANSLATION_Y);
+
+ mBadge = getBadge(info, appState, outObj[0]);
+ int blurMargin = (int) blurSizeOutline / 2;
+ mBadge.setBounds(blurMargin, blurMargin, w - blurMargin, h - blurMargin);
+
+ new Handler(Looper.getMainLooper()).post(new Runnable() {
+ @Override
+ public void run() {
+ // Assign the variable on the UI thread to avoid race conditions.
+ mScaledMaskPath = mask;
+ addView(mBgImageView);
+ addView(mFgImageView);
+ setWillNotDraw(true);
+ }
+ });
+ }
}});
}
- private ImageView setupImageView(Drawable drawable) {
+ /**
+ * Returns the full drawable for {@param info}.
+ * @param outObj this is set to the internal data associated with {@param info},
+ * eg {@link LauncherActivityInfo} or {@link ShortcutInfoCompat}.
+ */
+ private Drawable getFullDrawable(ItemInfo info, LauncherAppState appState, Object[] outObj) {
+ if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
+ LauncherActivityInfo activityInfo = LauncherAppsCompat.getInstance(mLauncher)
+ .resolveActivity(info.getIntent(), info.user);
+ outObj[0] = activityInfo;
+ return (activityInfo != null) ? appState.getIconCache()
+ .getFullResIcon(activityInfo) : null;
+ } else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
+ if (info instanceof PendingAddShortcutInfo) {
+ ShortcutConfigActivityInfo activityInfo =
+ ((PendingAddShortcutInfo) info).activityInfo;
+ outObj[0] = activityInfo;
+ return activityInfo.getFullResIcon(appState.getIconCache());
+ }
+ ShortcutKey key = ShortcutKey.fromItemInfo(info);
+ DeepShortcutManager sm = DeepShortcutManager.getInstance(mLauncher);
+ List<ShortcutInfoCompat> si = sm.queryForFullDetails(
+ key.componentName.getPackageName(), Arrays.asList(key.getId()), key.user);
+ if (si.isEmpty()) {
+ return null;
+ } else {
+ outObj[0] = si.get(0);
+ return sm.getShortcutIconDrawable(si.get(0),
+ appState.getInvariantDeviceProfile().fillResIconDpi);
+ }
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * For apps icons and shortcut icons that have badges, this method creates a drawable that can
+ * later on be rendered on top of the layers for the badges. For app icons, work profile badges
+ * can only be applied. For deep shortcuts, when dragged from the pop up container, there's no
+ * badge. When dragged from workspace or folder, it may contain app AND/OR work profile badge
+ **/
+
+ @TargetApi(Build.VERSION_CODES.O)
+ private Drawable getBadge(ItemInfo info, LauncherAppState appState, Object obj) {
+ int iconSize = appState.getInvariantDeviceProfile().iconBitmapSize;
+ if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
+ if (info.id == ItemInfo.NO_ID || !(obj instanceof ShortcutInfoCompat)) {
+ // The item is not yet added on home screen.
+ return new FixedSizeEmptyDrawable(iconSize);
+ }
+ ShortcutInfoCompat si = (ShortcutInfoCompat) obj;
+ Bitmap badge = LauncherIcons.getShortcutInfoBadge(si, appState.getIconCache());
+
+ float badgeSize = mLauncher.getResources().getDimension(R.dimen.profile_badge_size);
+ float insetFraction = (iconSize - badgeSize) / iconSize;
+ return new InsetDrawable(new FastBitmapDrawable(badge),
+ insetFraction, insetFraction, 0, 0);
+ } else {
+ return mLauncher.getPackageManager()
+ .getUserBadgedIcon(new FixedSizeEmptyDrawable(iconSize), info.user);
+ }
+ }
+
+ private ImageView setupImageView(Drawable drawable, float normalizationScale) {
FrameLayout.LayoutParams params = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
ImageView imageViewOut = new ImageView(getContext());
imageViewOut.setLayoutParams(params);
- imageViewOut.setScaleType(ImageView.ScaleType.CENTER);
- imageViewOut.setScaleX(ADAPTIVE_ICON_SCALE);
- imageViewOut.setScaleY(ADAPTIVE_ICON_SCALE);
+ imageViewOut.setScaleType(ImageView.ScaleType.FIT_XY);
+ imageViewOut.setScaleX(normalizationScale);
+ imageViewOut.setScaleY(normalizationScale);
imageViewOut.setImageDrawable(drawable);
return imageViewOut;
}
@@ -246,14 +335,16 @@
return s;
}
- private void setupMaskPath(AdaptiveIconDrawable dr) {
+ @TargetApi(Build.VERSION_CODES.O)
+ private Path getMaskPath(AdaptiveIconDrawable dr, float normalizationScale) {
Matrix m = new Matrix();
- m.setScale(ADAPTIVE_ICON_SCALE * ADAPTIVE_ICON_MASK_SCALE,
- ADAPTIVE_ICON_SCALE * ADAPTIVE_ICON_MASK_SCALE,
- dr.getBounds().centerX(),
- dr.getBounds().centerY());
- mScaledMaskPath = new Path();
- dr.getIconMask().transform(m, mScaledMaskPath);
+ // Shrink very tiny bit so that the clip path is smaller than the original bitmap
+ // that has anti aliased edges and shadows.
+ float s = normalizationScale * .97f;
+ m.setScale(s, s, dr.getBounds().centerX(), dr.getBounds().centerY());
+ Path p = new Path();
+ dr.getIconMask().transform(m, p);
+ return p;
}
private void applySpring(int x, int y) {
@@ -286,10 +377,15 @@
@Override
protected void dispatchDraw(Canvas canvas) {
if (mScaledMaskPath != null) {
+ int cnt = canvas.save();
canvas.drawBitmap(mBitmap, 0.0f, 0.0f, mPaint);
canvas.clipPath(mScaledMaskPath);
+ super.dispatchDraw(canvas);
+ canvas.restoreToCount(cnt);
+ mBadge.draw(canvas);
+ } else {
+ super.dispatchDraw(canvas);
}
- super.dispatchDraw(canvas);
}
/** Sets the scale of the view over the normal workspace icon size. */
@@ -535,4 +631,24 @@
public float getInitialScale() {
return mInitialScale;
}
+
+ private static class FixedSizeEmptyDrawable extends ColorDrawable {
+
+ private final int mSize;
+
+ public FixedSizeEmptyDrawable(int size) {
+ super(Color.TRANSPARENT);
+ mSize = size;
+ }
+
+ @Override
+ public int getIntrinsicHeight() {
+ return mSize;
+ }
+
+ @Override
+ public int getIntrinsicWidth() {
+ return mSize;
+ }
+ }
}
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index b6f05f3..48d8e10 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -510,6 +510,10 @@
Drawable d = params.drawable;
if (d != null) {
+ // Remove the callback to prevent invalidate as a result of property changes
+ Drawable.Callback cb = d.getCallback();
+ d.setCallback(null);
+
mTempBounds.set(d.getBounds());
d.setBounds(0, 0, mIntrinsicIconSize, mIntrinsicIconSize);
boolean isPreloadIcon = d instanceof PreloadIconDrawable;
@@ -523,6 +527,7 @@
d.clearColorFilter();
}
d.setBounds(mTempBounds);
+ d.setCallback(cb);
}
canvas.restore();
}
diff --git a/src/com/android/launcher3/graphics/LauncherIcons.java b/src/com/android/launcher3/graphics/LauncherIcons.java
index 19e5702..db03a04 100644
--- a/src/com/android/launcher3/graphics/LauncherIcons.java
+++ b/src/com/android/launcher3/graphics/LauncherIcons.java
@@ -329,7 +329,10 @@
return unbadgedBitmap;
}
unbadgedBitmap = LauncherIcons.addShadowToIcon(unbadgedBitmap, context);
+ return badgeWithBitmap(unbadgedBitmap, getShortcutInfoBadge(shortcutInfo, cache), context);
+ }
+ public static Bitmap getShortcutInfoBadge(ShortcutInfoCompat shortcutInfo, IconCache cache) {
final Bitmap badgeBitmap;
ComponentName cn = shortcutInfo.getActivity();
if (cn != null) {
@@ -347,7 +350,7 @@
cache.getTitleAndIconForApp(pkgInfo, false);
badgeBitmap = pkgInfo.iconBitmap;
}
- return badgeWithBitmap(unbadgedBitmap, badgeBitmap, context);
+ return badgeBitmap;
}
/**