diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java index 8b7a750cc7..c7323d025b 100644 --- a/src/com/android/launcher3/WidgetPreviewLoader.java +++ b/src/com/android/launcher3/WidgetPreviewLoader.java @@ -385,27 +385,29 @@ public class WidgetPreviewLoader { previewHeight = Math.max((int)(scale * previewHeight), 1); } - // If a bitmap is passed in, we use it; otherwise, we create a bitmap of the right size final Canvas c = new Canvas(); if (preview == null) { + // If no bitmap was provided, then allocate a new one with the right size. preview = Bitmap.createBitmap(previewWidth, previewHeight, Config.ARGB_8888); c.setBitmap(preview); } else { - // We use the preview bitmap height to determine where the badge will be drawn in the - // UI. If its larger than what we need, resize the preview bitmap so that there are - // no transparent pixels between the preview and the badge. - if (preview.getHeight() > previewHeight) { - preview.reconfigure(preview.getWidth(), previewHeight, preview.getConfig()); + // If a bitmap was passed in, attempt to reconfigure the bitmap to the same dimensions + // as the preview. + try { + preview.reconfigure(previewWidth, previewHeight, preview.getConfig()); + } catch (IllegalArgumentException e) { + // This occurs if the preview can't be reconfigured for any reason. In this case, + // allocate a new bitmap with the right size. + preview = Bitmap.createBitmap(previewWidth, previewHeight, Config.ARGB_8888); } - // Reusing bitmap. Clear it. + c.setBitmap(preview); c.drawColor(0, PorterDuff.Mode.CLEAR); } // Draw the scaled preview into the final bitmap - int x = (preview.getWidth() - previewWidth) / 2; if (widgetPreviewExists) { - drawable.setBounds(x, 0, x + previewWidth, previewHeight); + drawable.setBounds(0, 0, previewWidth, previewHeight); drawable.draw(c); } else { RectF boxRect; @@ -565,6 +567,7 @@ public class WidgetPreviewLoader { @Thunk long[] mVersions; @Thunk Bitmap mBitmapToRecycle; + @Nullable private Bitmap mUnusedPreviewBitmap; private boolean mSaveToDB = false; PreviewLoadTask(WidgetCacheKey key, WidgetItem info, int previewWidth, @@ -625,6 +628,11 @@ public class WidgetPreviewLoader { Pair pair = generatePreview(mActivity, mInfo, unusedBitmap, mPreviewWidth, mPreviewHeight); preview = pair.first; + + if (preview != unusedBitmap) { + mUnusedPreviewBitmap = unusedBitmap; + } + this.mSaveToDB = pair.second; } return preview; @@ -639,6 +647,14 @@ public class WidgetPreviewLoader { MODEL_EXECUTOR.post(new Runnable() { @Override public void run() { + if (mUnusedPreviewBitmap != null) { + // If we didn't end up using the bitmap, it can be added back into the + // recycled set. + synchronized (mUnusedBitmaps) { + mUnusedBitmaps.add(mUnusedPreviewBitmap); + } + } + if (!isCancelled() && mSaveToDB) { // If we are still using this preview, then write it to the DB and then // let the normal clear mechanism recycle the bitmap diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java index f7993dc408..7d04d7b404 100644 --- a/src/com/android/launcher3/widget/WidgetCell.java +++ b/src/com/android/launcher3/widget/WidgetCell.java @@ -95,6 +95,7 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener { protected final BaseActivity mActivity; private final CheckLongPressHelper mLongPressHelper; private final float mEnforcedCornerRadius; + private final int mPreviewPadding; private RemoteViews mRemoteViewsPreview; private NavigableAppWidgetHostView mAppWidgetHostViewPreview; @@ -119,6 +120,8 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener { setClipToPadding(false); setAccessibilityDelegate(mActivity.getAccessibilityDelegate()); mEnforcedCornerRadius = RoundedCornerEnforcement.computeEnforcedRadius(context); + mPreviewPadding = + 2 * getResources().getDimensionPixelSize(R.dimen.widget_preview_shortcut_padding); } private void setContainerWidth() { @@ -281,7 +284,16 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener { return; } if (drawable != null) { - setContainerSize(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); + float scale = 1f; + if (getWidth() > 0 && getHeight() > 0) { + // Scale down the preview size if it's wider than the cell. + float maxWidth = getWidth() - mPreviewPadding; + float previewWidth = drawable.getIntrinsicWidth() * mPreviewScale; + scale = Math.min(maxWidth / previewWidth, 1); + } + setContainerSize( + Math.round(drawable.getIntrinsicWidth() * scale), + Math.round(drawable.getIntrinsicHeight() * scale)); mWidgetImage.setDrawable(drawable); mWidgetImage.setVisibility(View.VISIBLE); if (mAppWidgetHostViewPreview != null) { @@ -330,11 +342,9 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener { /** Sets the widget preview image size, in number of cells, and preview scale. */ public void setPreviewSize(int spanX, int spanY, float previewScale) { - int padding = 2 * getResources() - .getDimensionPixelSize(R.dimen.widget_preview_shortcut_padding); DeviceProfile deviceProfile = mActivity.getDeviceProfile(); - mPreviewWidth = deviceProfile.cellWidthPx * spanX + padding; - mPreviewHeight = deviceProfile.cellHeightPx * spanY + padding; + mPreviewWidth = deviceProfile.cellWidthPx * spanX + mPreviewPadding; + mPreviewHeight = deviceProfile.cellHeightPx * spanY + mPreviewPadding; mPreviewScale = previewScale; }