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
This commit is contained in:
Sunny Goyal
2017-09-26 12:43:16 -07:00
parent f00c5b5fd4
commit aa3a2baab6
8 changed files with 151 additions and 225 deletions
+11 -21
View File
@@ -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;
}
@@ -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;
@@ -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;
}
}
}
@@ -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<Bitmap> 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) {
@@ -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();
@@ -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);
@@ -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;
}
}
@@ -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],