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:
@@ -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],
|
||||
|
||||
Reference in New Issue
Block a user