From aa3a2baab60e874a410fed6e958e1fb63c75fa37 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Tue, 26 Sep 2017 12:43:16 -0700 Subject: [PATCH] Simplifying drag preview generation > Fixing wrong icon normalization when dragging a folder icon > Reusing the preview bitmap for creating dragOutline > Generating drag outline on the background thread Bug: 35428783 Change-Id: I01e724ba63404302090ee1e562f6c2fc7147ba2f --- src/com/android/launcher3/Workspace.java | 32 ++--- .../android/launcher3/dragndrop/DragView.java | 6 +- .../graphics/DragPreviewProvider.java | 136 +++++++++++++----- .../graphics/HolographicOutlineHelper.java | 90 +----------- .../launcher3/graphics/IconNormalizer.java | 18 ++- .../ShortcutDragPreviewProvider.java | 25 +--- .../widget/PendingItemDragHelper.java | 67 +++------ .../widget/WidgetHostViewLoader.java | 2 +- 8 files changed, 151 insertions(+), 225 deletions(-) diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index dfcb3314f2..c82731ff83 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -252,8 +252,6 @@ public class Workspace extends PagedView private boolean mAddToExistingFolderOnDrop = false; private float mMaxDistanceForFolderCreation; - private final Canvas mCanvas = new Canvas(); - // Variables relating to touch disambiguation (scrolling workspace vs. scrolling a widget) private float mXDown; private float mYDown; @@ -351,12 +349,9 @@ public class Workspace extends PagedView /** * Estimates the size of an item using spans: hSpan, vSpan. * - * @param springLoaded True if we are in spring loaded mode. - * @param unscaledSize True if caller wants to return the unscaled size * @return MAX_VALUE for each dimension if unsuccessful. */ - public int[] estimateItemSize(ItemInfo itemInfo, boolean springLoaded, boolean unscaledSize) { - float shrinkFactor = mLauncher.getDeviceProfile().workspaceSpringLoadShrinkFactor; + public int[] estimateItemSize(ItemInfo itemInfo) { int[] size = new int[2]; if (getChildCount() > 0) { // Use the first page to estimate the child position @@ -373,15 +368,10 @@ public class Workspace extends PagedView size[0] = r.width(); size[1] = r.height(); - if (isWidget && unscaledSize) { + if (isWidget) { size[0] /= scale; size[1] /= scale; } - - if (springLoaded) { - size[0] *= shrinkFactor; - size[1] *= shrinkFactor; - } return size; } else { size[0] = Integer.MAX_VALUE; @@ -408,8 +398,12 @@ public class Workspace extends PagedView } if (mOutlineProvider != null) { - // The outline is used to visualize where the item will land if dropped - mOutlineProvider.generateDragOutline(mCanvas); + if (dragObject.dragView != null) { + Bitmap preview = dragObject.dragView.getPreviewBitmap(); + + // The outline is used to visualize where the item will land if dropped + mOutlineProvider.generateDragOutline(preview); + } } updateChildrenLayersEnabled(false); @@ -1833,7 +1827,7 @@ public class Workspace extends PagedView mOutlineProvider = previewProvider; // The drag bitmap follows the touch point around on the screen - final Bitmap b = previewProvider.createDragBitmap(mCanvas); + final Bitmap b = previewProvider.createDragBitmap(); int halfPadding = previewProvider.previewPadding / 2; float scale = previewProvider.getScaleAndPosition(b, mTempXY); @@ -1881,7 +1875,6 @@ public class Workspace extends PagedView DragView dv = mDragController.startDrag(b, dragLayerX, dragLayerY, source, dragObject, dragVisualizeOffset, dragRect, scale, dragOptions); dv.setIntrinsicIconScaleFactor(source.getIntrinsicIconScaleFactor()); - b.recycle(); return dv; } @@ -2992,7 +2985,7 @@ public class Workspace extends PagedView } public Bitmap createWidgetBitmap(ItemInfo widgetInfo, View layout) { - int[] unScaledSize = mLauncher.getWorkspace().estimateItemSize(widgetInfo, false, true); + int[] unScaledSize = estimateItemSize(widgetInfo); int visibility = layout.getVisibility(); layout.setVisibility(VISIBLE); @@ -3000,12 +2993,9 @@ public class Workspace extends PagedView int height = MeasureSpec.makeMeasureSpec(unScaledSize[1], MeasureSpec.EXACTLY); Bitmap b = Bitmap.createBitmap(unScaledSize[0], unScaledSize[1], Bitmap.Config.ARGB_8888); - mCanvas.setBitmap(b); - layout.measure(width, height); layout.layout(0, 0, unScaledSize[0], unScaledSize[1]); - layout.draw(mCanvas); - mCanvas.setBitmap(null); + layout.draw(new Canvas(b)); layout.setVisibility(visibility); return b; } diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java index 33d4fa628a..17fad84968 100644 --- a/src/com/android/launcher3/dragndrop/DragView.java +++ b/src/com/android/launcher3/dragndrop/DragView.java @@ -169,7 +169,7 @@ public class DragView extends View { } }); - mBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight()); + mBitmap = bitmap; setDragRegion(new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight())); // The point in our scaled bitmap that the touch events are located @@ -427,6 +427,10 @@ public class DragView extends View { return mDragRegion; } + public Bitmap getPreviewBitmap() { + return mBitmap; + } + @Override protected void onDraw(Canvas canvas) { mHasDrawn = true; diff --git a/src/com/android/launcher3/graphics/DragPreviewProvider.java b/src/com/android/launcher3/graphics/DragPreviewProvider.java index 10e91c0a83..0989921b28 100644 --- a/src/com/android/launcher3/graphics/DragPreviewProvider.java +++ b/src/com/android/launcher3/graphics/DragPreviewProvider.java @@ -18,19 +18,27 @@ package com.android.launcher3.graphics; import android.content.Context; import android.graphics.Bitmap; +import android.graphics.BlurMaskFilter; import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.Region.Op; import android.graphics.drawable.Drawable; +import android.os.Handler; import android.view.View; import com.android.launcher3.BubbleTextView; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppWidgetHostView; +import com.android.launcher3.LauncherModel; import com.android.launcher3.R; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.folder.FolderIcon; +import java.nio.ByteBuffer; + /** * A utility class to generate preview bitmap for dragging. */ @@ -45,6 +53,7 @@ public class DragPreviewProvider { protected final int blurSizeOutline; + private OutlineGeneratorCallback mOutlineGeneratorCallback; public Bitmap generatedDragOutline; public DragPreviewProvider(View view) { @@ -106,7 +115,7 @@ public class DragPreviewProvider { * Returns a new bitmap to show when the {@link #mView} is being dragged around. * Responsibility for the bitmap is transferred to the caller. */ - public Bitmap createDragBitmap(Canvas canvas) { + public Bitmap createDragBitmap() { float scale = 1f; int width = mView.getWidth(); int height = mView.getHeight(); @@ -124,7 +133,7 @@ public class DragPreviewProvider { Bitmap b = Bitmap.createBitmap(width + blurSizeOutline, height + blurSizeOutline, Bitmap.Config.ARGB_8888); - canvas.setBitmap(b); + Canvas canvas = new Canvas(b); canvas.save(); canvas.scale(scale, scale); @@ -136,43 +145,13 @@ public class DragPreviewProvider { return b; } - public final void generateDragOutline(Canvas canvas) { - if (FeatureFlags.IS_DOGFOOD_BUILD && generatedDragOutline != null) { + public final void generateDragOutline(Bitmap preview) { + if (FeatureFlags.IS_DOGFOOD_BUILD && mOutlineGeneratorCallback != null) { throw new RuntimeException("Drag outline generated twice"); } - generatedDragOutline = createDragOutline(canvas); - } - - /** - * Returns a new bitmap to be used as the object outline, e.g. to visualize the drop location. - * Responsibility for the bitmap is transferred to the caller. - */ - public Bitmap createDragOutline(Canvas canvas) { - float scale = 1f; - int width = mView.getWidth(); - int height = mView.getHeight(); - - if (mView instanceof LauncherAppWidgetHostView) { - scale = ((LauncherAppWidgetHostView) mView).getScaleToFit(); - width = (int) Math.floor(mView.getWidth() * scale); - height = (int) Math.floor(mView.getHeight() * scale); - } - - Bitmap b = Bitmap.createBitmap(width + blurSizeOutline, height + blurSizeOutline, - Bitmap.Config.ALPHA_8); - canvas.setBitmap(b); - - canvas.save(); - canvas.scale(scale, scale); - drawDragView(canvas); - canvas.restore(); - - HolographicOutlineHelper.getInstance(mView.getContext()) - .applyExpensiveOutlineWithBlur(b, canvas); - - canvas.setBitmap(null); - return b; + mOutlineGeneratorCallback = new OutlineGeneratorCallback(preview); + new Handler(LauncherModel.getWorkerLooper()).postAtFrontOfQueue(mOutlineGeneratorCallback); } protected static Rect getDrawableBounds(Drawable d) { @@ -201,4 +180,89 @@ public class DragPreviewProvider { - previewPadding / 2); return scale; } + + protected Bitmap convertPreviewToAlphaBitmap(Bitmap preview) { + return preview.copy(Bitmap.Config.ALPHA_8, true); + } + + private class OutlineGeneratorCallback implements Runnable { + + private final Bitmap mPreviewSnapshot; + private final Context mContext; + + OutlineGeneratorCallback(Bitmap preview) { + mPreviewSnapshot = preview; + mContext = mView.getContext(); + } + + @Override + public void run() { + Bitmap preview = convertPreviewToAlphaBitmap(mPreviewSnapshot); + + // We start by removing most of the alpha channel so as to ignore shadows, and + // other types of partial transparency when defining the shape of the object + byte[] pixels = new byte[preview.getWidth() * preview.getHeight()]; + ByteBuffer buffer = ByteBuffer.wrap(pixels); + buffer.rewind(); + preview.copyPixelsToBuffer(buffer); + + for (int i = 0; i < pixels.length; i++) { + if ((pixels[i] & 0xFF) < 188) { + pixels[i] = 0; + } + } + + buffer.rewind(); + preview.copyPixelsFromBuffer(buffer); + + final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); + Canvas canvas = new Canvas(); + + // calculate the outer blur first + paint.setMaskFilter(new BlurMaskFilter(blurSizeOutline, BlurMaskFilter.Blur.OUTER)); + int[] outerBlurOffset = new int[2]; + Bitmap thickOuterBlur = preview.extractAlpha(paint, outerBlurOffset); + + paint.setMaskFilter(new BlurMaskFilter( + mContext.getResources().getDimension(R.dimen.blur_size_thin_outline), + BlurMaskFilter.Blur.OUTER)); + int[] brightOutlineOffset = new int[2]; + Bitmap brightOutline = preview.extractAlpha(paint, brightOutlineOffset); + + // calculate the inner blur + canvas.setBitmap(preview); + canvas.drawColor(0xFF000000, PorterDuff.Mode.SRC_OUT); + paint.setMaskFilter(new BlurMaskFilter(blurSizeOutline, BlurMaskFilter.Blur.NORMAL)); + int[] thickInnerBlurOffset = new int[2]; + Bitmap thickInnerBlur = preview.extractAlpha(paint, thickInnerBlurOffset); + + // mask out the inner blur + paint.setMaskFilter(null); + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); + canvas.setBitmap(thickInnerBlur); + canvas.drawBitmap(preview, -thickInnerBlurOffset[0], + -thickInnerBlurOffset[1], paint); + canvas.drawRect(0, 0, -thickInnerBlurOffset[0], thickInnerBlur.getHeight(), paint); + canvas.drawRect(0, 0, thickInnerBlur.getWidth(), -thickInnerBlurOffset[1], paint); + + // draw the inner and outer blur + paint.setXfermode(null); + canvas.setBitmap(preview); + canvas.drawColor(0, PorterDuff.Mode.CLEAR); + canvas.drawBitmap(thickInnerBlur, thickInnerBlurOffset[0], thickInnerBlurOffset[1], + paint); + canvas.drawBitmap(thickOuterBlur, outerBlurOffset[0], outerBlurOffset[1], paint); + + // draw the bright outline + canvas.drawBitmap(brightOutline, brightOutlineOffset[0], brightOutlineOffset[1], paint); + + // cleanup + canvas.setBitmap(null); + brightOutline.recycle(); + thickOuterBlur.recycle(); + thickInnerBlur.recycle(); + + generatedDragOutline = preview; + } + } } diff --git a/src/com/android/launcher3/graphics/HolographicOutlineHelper.java b/src/com/android/launcher3/graphics/HolographicOutlineHelper.java index b221828837..9e67f56e3f 100644 --- a/src/com/android/launcher3/graphics/HolographicOutlineHelper.java +++ b/src/com/android/launcher3/graphics/HolographicOutlineHelper.java @@ -17,7 +17,6 @@ package com.android.launcher3.graphics; import android.content.Context; -import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BlurMaskFilter; import android.graphics.Canvas; @@ -31,9 +30,6 @@ import android.util.SparseArray; import com.android.launcher3.BubbleTextView; import com.android.launcher3.R; -import com.android.launcher3.config.FeatureFlags; - -import java.nio.ByteBuffer; /** * Utility class to generate shadow and outline effect, which are used for click feedback @@ -44,14 +40,9 @@ public class HolographicOutlineHelper { private static HolographicOutlineHelper sInstance; private final Canvas mCanvas = new Canvas(); - private final Paint mDrawPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); private final Paint mBlurPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); private final Paint mErasePaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); - private final BlurMaskFilter mMediumOuterBlurMaskFilter; - private final BlurMaskFilter mThinOuterBlurMaskFilter; - private final BlurMaskFilter mMediumInnerBlurMaskFilter; - private final float mShadowBitmapShift; private final BlurMaskFilter mShadowBlurMaskFilter; @@ -59,18 +50,8 @@ public class HolographicOutlineHelper { private final SparseArray mBitmapCache = new SparseArray<>(4); private HolographicOutlineHelper(Context context) { - Resources res = context.getResources(); - - float mediumBlur = res.getDimension(R.dimen.blur_size_medium_outline); - mMediumOuterBlurMaskFilter = new BlurMaskFilter(mediumBlur, BlurMaskFilter.Blur.OUTER); - mMediumInnerBlurMaskFilter = new BlurMaskFilter(mediumBlur, BlurMaskFilter.Blur.NORMAL); - - mThinOuterBlurMaskFilter = new BlurMaskFilter( - res.getDimension(R.dimen.blur_size_thin_outline), BlurMaskFilter.Blur.OUTER); - - mShadowBitmapShift = res.getDimension(R.dimen.blur_size_click_shadow); + mShadowBitmapShift = context.getResources().getDimension(R.dimen.blur_size_click_shadow); mShadowBlurMaskFilter = new BlurMaskFilter(mShadowBitmapShift, BlurMaskFilter.Blur.NORMAL); - mErasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); } @@ -81,75 +62,6 @@ public class HolographicOutlineHelper { return sInstance; } - /** - * Applies a more expensive and accurate outline to whatever is currently drawn in a specified - * bitmap. - */ - public void applyExpensiveOutlineWithBlur(Bitmap srcDst, Canvas srcDstCanvas) { - if (FeatureFlags.IS_DOGFOOD_BUILD && srcDst.getConfig() != Bitmap.Config.ALPHA_8) { - throw new RuntimeException("Outline blue is only supported on alpha bitmaps"); - } - - // We start by removing most of the alpha channel so as to ignore shadows, and - // other types of partial transparency when defining the shape of the object - byte[] pixels = new byte[srcDst.getWidth() * srcDst.getHeight()]; - ByteBuffer buffer = ByteBuffer.wrap(pixels); - buffer.rewind(); - srcDst.copyPixelsToBuffer(buffer); - - for (int i = 0; i < pixels.length; i++) { - if ((pixels[i] & 0xFF) < 188) { - pixels[i] = 0; - } - } - - buffer.rewind(); - srcDst.copyPixelsFromBuffer(buffer); - - // calculate the outer blur first - mBlurPaint.setMaskFilter(mMediumOuterBlurMaskFilter); - int[] outerBlurOffset = new int[2]; - Bitmap thickOuterBlur = srcDst.extractAlpha(mBlurPaint, outerBlurOffset); - - mBlurPaint.setMaskFilter(mThinOuterBlurMaskFilter); - int[] brightOutlineOffset = new int[2]; - Bitmap brightOutline = srcDst.extractAlpha(mBlurPaint, brightOutlineOffset); - - // calculate the inner blur - srcDstCanvas.setBitmap(srcDst); - srcDstCanvas.drawColor(0xFF000000, PorterDuff.Mode.SRC_OUT); - mBlurPaint.setMaskFilter(mMediumInnerBlurMaskFilter); - int[] thickInnerBlurOffset = new int[2]; - Bitmap thickInnerBlur = srcDst.extractAlpha(mBlurPaint, thickInnerBlurOffset); - - // mask out the inner blur - srcDstCanvas.setBitmap(thickInnerBlur); - srcDstCanvas.drawBitmap(srcDst, -thickInnerBlurOffset[0], - -thickInnerBlurOffset[1], mErasePaint); - srcDstCanvas.drawRect(0, 0, -thickInnerBlurOffset[0], thickInnerBlur.getHeight(), - mErasePaint); - srcDstCanvas.drawRect(0, 0, thickInnerBlur.getWidth(), -thickInnerBlurOffset[1], - mErasePaint); - - // draw the inner and outer blur - srcDstCanvas.setBitmap(srcDst); - srcDstCanvas.drawColor(0, PorterDuff.Mode.CLEAR); - srcDstCanvas.drawBitmap(thickInnerBlur, thickInnerBlurOffset[0], thickInnerBlurOffset[1], - mDrawPaint); - srcDstCanvas.drawBitmap(thickOuterBlur, outerBlurOffset[0], outerBlurOffset[1], - mDrawPaint); - - // draw the bright outline - srcDstCanvas.drawBitmap(brightOutline, brightOutlineOffset[0], brightOutlineOffset[1], - mDrawPaint); - - // cleanup - srcDstCanvas.setBitmap(null); - brightOutline.recycle(); - thickOuterBlur.recycle(); - thickInnerBlur.recycle(); - } - public Bitmap createMediumDropShadow(BubbleTextView view) { Drawable drawable = view.getIcon(); if (drawable == null) { diff --git a/src/com/android/launcher3/graphics/IconNormalizer.java b/src/com/android/launcher3/graphics/IconNormalizer.java index 28fc423685..5ee6a30b76 100644 --- a/src/com/android/launcher3/graphics/IconNormalizer.java +++ b/src/com/android/launcher3/graphics/IconNormalizer.java @@ -28,12 +28,15 @@ import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.AdaptiveIconDrawable; +import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.util.Log; import com.android.launcher3.LauncherAppState; import com.android.launcher3.Utilities; +import com.android.launcher3.dragndrop.FolderAdaptiveIcon; + import java.io.File; import java.io.FileOutputStream; import java.nio.ByteBuffer; @@ -231,12 +234,17 @@ public class IconNormalizer { */ public synchronized float getScale(@NonNull Drawable d, @Nullable RectF outBounds, @Nullable Path path, @Nullable boolean[] outMaskShape) { - if (Utilities.ATLEAST_OREO && d instanceof AdaptiveIconDrawable && - mAdaptiveIconScale != SCALE_NOT_INITIALIZED) { - if (outBounds != null) { - outBounds.set(mAdaptiveIconBounds); + if (Utilities.ATLEAST_OREO && d instanceof AdaptiveIconDrawable) { + if (mAdaptiveIconScale != SCALE_NOT_INITIALIZED) { + if (outBounds != null) { + outBounds.set(mAdaptiveIconBounds); + } + return mAdaptiveIconScale; + } + if (d instanceof FolderAdaptiveIcon) { + // Since we just want the scale, avoid heavy drawing operations + d = new AdaptiveIconDrawable(new ColorDrawable(Color.BLACK), null); } - return mAdaptiveIconScale; } int width = d.getIntrinsicWidth(); int height = d.getIntrinsicHeight(); diff --git a/src/com/android/launcher3/shortcuts/ShortcutDragPreviewProvider.java b/src/com/android/launcher3/shortcuts/ShortcutDragPreviewProvider.java index e9d2b50eae..cfb9258dd9 100644 --- a/src/com/android/launcher3/shortcuts/ShortcutDragPreviewProvider.java +++ b/src/com/android/launcher3/shortcuts/ShortcutDragPreviewProvider.java @@ -26,7 +26,6 @@ import android.view.View; import com.android.launcher3.Launcher; import com.android.launcher3.Utilities; import com.android.launcher3.graphics.DragPreviewProvider; -import com.android.launcher3.graphics.HolographicOutlineHelper; /** * Extension of {@link DragPreviewProvider} which generates bitmaps scaled to the default icon size. @@ -40,35 +39,17 @@ public class ShortcutDragPreviewProvider extends DragPreviewProvider { mPositionShift = shift; } - @Override - public Bitmap createDragOutline(Canvas canvas) { - Bitmap b = drawScaledPreview(canvas, Bitmap.Config.ALPHA_8); - - HolographicOutlineHelper.getInstance(mView.getContext()) - .applyExpensiveOutlineWithBlur(b, canvas); - canvas.setBitmap(null); - return b; - } - - @Override - public Bitmap createDragBitmap(Canvas canvas) { - Bitmap b = drawScaledPreview(canvas, Bitmap.Config.ARGB_8888); - canvas.setBitmap(null); - return b; - } - - private Bitmap drawScaledPreview(Canvas canvas, Bitmap.Config config) { + public Bitmap createDragBitmap() { Drawable d = mView.getBackground(); Rect bounds = getDrawableBounds(d); int size = Launcher.getLauncher(mView.getContext()).getDeviceProfile().iconSizePx; - final Bitmap b = Bitmap.createBitmap( size + blurSizeOutline, size + blurSizeOutline, - config); + Bitmap.Config.ARGB_8888); - canvas.setBitmap(b); + Canvas canvas = new Canvas(b); canvas.save(Canvas.MATRIX_SAVE_FLAG); canvas.translate(blurSizeOutline / 2, blurSizeOutline / 2); canvas.scale(((float) size) / bounds.width(), ((float) size) / bounds.height(), 0, 0); diff --git a/src/com/android/launcher3/widget/PendingItemDragHelper.java b/src/com/android/launcher3/widget/PendingItemDragHelper.java index 19be28d832..c5cf5e23a4 100644 --- a/src/com/android/launcher3/widget/PendingItemDragHelper.java +++ b/src/com/android/launcher3/widget/PendingItemDragHelper.java @@ -22,7 +22,6 @@ import android.graphics.Paint; import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.Drawable; -import android.os.Build; import android.view.View; import android.widget.RemoteViews; @@ -32,11 +31,9 @@ import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; import com.android.launcher3.PendingAddItemInfo; import com.android.launcher3.R; -import com.android.launcher3.Workspace; import com.android.launcher3.dragndrop.DragOptions; import com.android.launcher3.dragndrop.LivePreviewWidgetCell; import com.android.launcher3.graphics.DragPreviewProvider; -import com.android.launcher3.graphics.HolographicOutlineHelper; import com.android.launcher3.graphics.LauncherIcons; /** @@ -48,8 +45,8 @@ public class PendingItemDragHelper extends DragPreviewProvider { private static final float MAX_WIDGET_SCALE = 1.25f; private final PendingAddItemInfo mAddInfo; + private int[] mEstimatedCellSize; - private Bitmap mPreviewBitmap; private RemoteViews mPreview; public PendingItemDragHelper(View view) { @@ -80,12 +77,12 @@ public class PendingItemDragHelper extends DragPreviewProvider { final Point dragOffset; final Rect dragRegion; + mEstimatedCellSize = launcher.getWorkspace().estimateItemSize(mAddInfo); if (mAddInfo instanceof PendingAddWidgetInfo) { PendingAddWidgetInfo createWidgetInfo = (PendingAddWidgetInfo) mAddInfo; - int[] size = launcher.getWorkspace().estimateItemSize(createWidgetInfo, true, false); - int maxWidth = Math.min((int) (previewBitmapWidth * MAX_WIDGET_SCALE), size[0]); + int maxWidth = Math.min((int) (previewBitmapWidth * MAX_WIDGET_SCALE), mEstimatedCellSize[0]); int[] previewSizeBeforeScale = new int[1]; @@ -117,14 +114,12 @@ public class PendingItemDragHelper extends DragPreviewProvider { PendingAddShortcutInfo createShortcutInfo = (PendingAddShortcutInfo) mAddInfo; Drawable icon = createShortcutInfo.activityInfo.getFullResIcon(app.getIconCache()); preview = LauncherIcons.createScaledBitmapWithoutShadow(icon, launcher, 0); - mAddInfo.spanX = mAddInfo.spanY = 1; scale = ((float) launcher.getDeviceProfile().iconSizePx) / preview.getWidth(); dragOffset = new Point(previewPadding / 2, previewPadding / 2); // Create a preview same as the workspace cell size and draw the icon at the // appropriate position. - int[] size = launcher.getWorkspace().estimateItemSize(mAddInfo, false, true); DeviceProfile dp = launcher.getDeviceProfile(); int iconSize = dp.iconSizePx; @@ -134,9 +129,10 @@ public class PendingItemDragHelper extends DragPreviewProvider { previewBounds.top += padding; dragRegion = new Rect(); - dragRegion.left = (size[0] - iconSize) / 2; + dragRegion.left = (mEstimatedCellSize[0] - iconSize) / 2; dragRegion.right = dragRegion.left + iconSize; - dragRegion.top = (size[1] - iconSize - dp.iconTextSizePx - dp.iconDrawablePaddingPx) / 2; + dragRegion.top = (mEstimatedCellSize[1] + - iconSize - dp.iconTextSizePx - dp.iconDrawablePaddingPx) / 2; dragRegion.bottom = dragRegion.top + iconSize; } @@ -149,60 +145,31 @@ public class PendingItemDragHelper extends DragPreviewProvider { int dragLayerY = screenPos.y + previewBounds.top + (int) ((scale * preview.getHeight() - preview.getHeight()) / 2); - mPreviewBitmap = preview; // Start the drag launcher.getDragController().startDrag(preview, dragLayerX, dragLayerY, source, mAddInfo, dragOffset, dragRegion, scale, options); } - @Override - public Bitmap createDragOutline(Canvas canvas) { - if (mAddInfo instanceof PendingAddShortcutInfo) { - int width = mPreviewBitmap.getWidth(); - int height = mPreviewBitmap.getHeight(); - Bitmap b = Bitmap.createBitmap(width + blurSizeOutline, height + blurSizeOutline, - Bitmap.Config.ALPHA_8); - canvas.setBitmap(b); - - Launcher launcher = Launcher.getLauncher(mView.getContext()); - int size = launcher.getDeviceProfile().iconSizePx; - - Rect src = new Rect(0, 0, mPreviewBitmap.getWidth(), mPreviewBitmap.getHeight()); - Rect dst = new Rect(0, 0, size, size); - dst.offset(blurSizeOutline / 2, blurSizeOutline / 2); - canvas.drawBitmap(mPreviewBitmap, src, dst, new Paint(Paint.FILTER_BITMAP_FLAG)); - - HolographicOutlineHelper.getInstance(mView.getContext()) - .applyExpensiveOutlineWithBlur(b, canvas); - - canvas.setBitmap(null); - return b; + protected Bitmap convertPreviewToAlphaBitmap(Bitmap preview) { + if (mAddInfo instanceof PendingAddShortcutInfo || mEstimatedCellSize == null) { + return super.convertPreviewToAlphaBitmap(preview); } - Workspace workspace = Launcher.getLauncher(mView.getContext()).getWorkspace(); - int[] size = workspace.estimateItemSize(mAddInfo, false, false); - - int w = size[0]; - int h = size[1]; + int w = mEstimatedCellSize[0]; + int h = mEstimatedCellSize[1]; final Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ALPHA_8); - canvas.setBitmap(b); + Rect src = new Rect(0, 0, preview.getWidth(), preview.getHeight()); - Rect src = new Rect(0, 0, mPreviewBitmap.getWidth(), mPreviewBitmap.getHeight()); - float scaleFactor = Math.min((w - blurSizeOutline) / (float) mPreviewBitmap.getWidth(), - (h - blurSizeOutline) / (float) mPreviewBitmap.getHeight()); - int scaledWidth = (int) (scaleFactor * mPreviewBitmap.getWidth()); - int scaledHeight = (int) (scaleFactor * mPreviewBitmap.getHeight()); + float scaleFactor = Math.min((w - blurSizeOutline) / (float) preview.getWidth(), + (h - blurSizeOutline) / (float) preview.getHeight()); + int scaledWidth = (int) (scaleFactor * preview.getWidth()); + int scaledHeight = (int) (scaleFactor * preview.getHeight()); Rect dst = new Rect(0, 0, scaledWidth, scaledHeight); // center the image dst.offset((w - scaledWidth) / 2, (h - scaledHeight) / 2); - - canvas.drawBitmap(mPreviewBitmap, src, dst, null); - HolographicOutlineHelper.getInstance(mView.getContext()) - .applyExpensiveOutlineWithBlur(b, canvas); - canvas.setBitmap(null); - + new Canvas(b).drawBitmap(preview, src, dst, new Paint(Paint.FILTER_BITMAP_FLAG)); return b; } } diff --git a/src/com/android/launcher3/widget/WidgetHostViewLoader.java b/src/com/android/launcher3/widget/WidgetHostViewLoader.java index e6f8bb68f5..8dcdd4465f 100644 --- a/src/com/android/launcher3/widget/WidgetHostViewLoader.java +++ b/src/com/android/launcher3/widget/WidgetHostViewLoader.java @@ -129,7 +129,7 @@ public class WidgetHostViewLoader implements DragController.DragListener { mWidgetLoadingId = -1; hostView.setVisibility(View.INVISIBLE); - int[] unScaledSize = mLauncher.getWorkspace().estimateItemSize(mInfo, false, true); + int[] unScaledSize = mLauncher.getWorkspace().estimateItemSize(mInfo); // We want the first widget layout to be the correct size. This will be important // for width size reporting to the AppWidgetManager. DragLayer.LayoutParams lp = new DragLayer.LayoutParams(unScaledSize[0],