1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.launcher3.widget; 18 19 import android.graphics.Bitmap; 20 import android.graphics.Canvas; 21 import android.graphics.Paint; 22 import android.graphics.Point; 23 import android.graphics.Rect; 24 import android.graphics.drawable.Drawable; 25 import android.view.View; 26 import android.widget.RemoteViews; 27 28 import com.android.launcher3.DeviceProfile; 29 import com.android.launcher3.DragSource; 30 import com.android.launcher3.Launcher; 31 import com.android.launcher3.LauncherAppState; 32 import com.android.launcher3.PendingAddItemInfo; 33 import com.android.launcher3.R; 34 import com.android.launcher3.dragndrop.DragOptions; 35 import com.android.launcher3.dragndrop.DraggableView; 36 import com.android.launcher3.dragndrop.LivePreviewWidgetCell; 37 import com.android.launcher3.graphics.DragPreviewProvider; 38 import com.android.launcher3.icons.LauncherIcons; 39 40 /** 41 * Extension of {@link DragPreviewProvider} with logic specific to pending widgets/shortcuts 42 * dragged from the widget tray. 43 */ 44 public class PendingItemDragHelper extends DragPreviewProvider { 45 46 private static final float MAX_WIDGET_SCALE = 1.25f; 47 48 private final PendingAddItemInfo mAddInfo; 49 private int[] mEstimatedCellSize; 50 51 private RemoteViews mPreview; 52 PendingItemDragHelper(View view)53 public PendingItemDragHelper(View view) { 54 super(view); 55 mAddInfo = (PendingAddItemInfo) view.getTag(); 56 } 57 setPreview(RemoteViews preview)58 public void setPreview(RemoteViews preview) { 59 mPreview = preview; 60 } 61 62 /** 63 * Starts the drag for the pending item associated with the view. 64 * 65 * @param previewBounds The bounds where the image was displayed, 66 * {@link WidgetImageView#getBitmapBounds()} 67 * @param previewBitmapWidth The actual width of the bitmap displayed in the view. 68 * @param previewViewWidth The width of {@link WidgetImageView} displaying the preview 69 * @param screenPos Position of {@link WidgetImageView} on the screen 70 */ startDrag(Rect previewBounds, int previewBitmapWidth, int previewViewWidth, Point screenPos, DragSource source, DragOptions options)71 public void startDrag(Rect previewBounds, int previewBitmapWidth, int previewViewWidth, 72 Point screenPos, DragSource source, DragOptions options) { 73 final Launcher launcher = Launcher.getLauncher(mView.getContext()); 74 LauncherAppState app = LauncherAppState.getInstance(launcher); 75 76 Bitmap preview = null; 77 final float scale; 78 final Point dragOffset; 79 final Rect dragRegion; 80 81 mEstimatedCellSize = launcher.getWorkspace().estimateItemSize(mAddInfo); 82 83 DraggableView draggableView; 84 85 if (mAddInfo instanceof PendingAddWidgetInfo) { 86 PendingAddWidgetInfo createWidgetInfo = (PendingAddWidgetInfo) mAddInfo; 87 88 int maxWidth = Math.min((int) (previewBitmapWidth * MAX_WIDGET_SCALE), mEstimatedCellSize[0]); 89 90 int[] previewSizeBeforeScale = new int[1]; 91 92 if (mPreview != null) { 93 preview = LivePreviewWidgetCell.generateFromRemoteViews(launcher, mPreview, 94 createWidgetInfo.info, maxWidth, previewSizeBeforeScale); 95 } 96 if (preview == null) { 97 preview = app.getWidgetCache().generateWidgetPreview(launcher, 98 createWidgetInfo.info, maxWidth, null, previewSizeBeforeScale).first; 99 } 100 101 if (previewSizeBeforeScale[0] < previewBitmapWidth) { 102 // The icon has extra padding around it. 103 int padding = (previewBitmapWidth - previewSizeBeforeScale[0]) / 2; 104 if (previewBitmapWidth > previewViewWidth) { 105 padding = padding * previewViewWidth / previewBitmapWidth; 106 } 107 108 previewBounds.left += padding; 109 previewBounds.right -= padding; 110 } 111 scale = previewBounds.width() / (float) preview.getWidth(); 112 launcher.getDragController().addDragListener(new WidgetHostViewLoader(launcher, mView)); 113 114 dragOffset = null; 115 dragRegion = null; 116 draggableView = DraggableView.ofType(DraggableView.DRAGGABLE_WIDGET); 117 } else { 118 PendingAddShortcutInfo createShortcutInfo = (PendingAddShortcutInfo) mAddInfo; 119 Drawable icon = createShortcutInfo.activityInfo.getFullResIcon(app.getIconCache()); 120 LauncherIcons li = LauncherIcons.obtain(launcher); 121 preview = li.createScaledBitmapWithoutShadow(icon, 0); 122 li.recycle(); 123 scale = ((float) launcher.getDeviceProfile().iconSizePx) / preview.getWidth(); 124 125 dragOffset = new Point(previewPadding / 2, previewPadding / 2); 126 127 // Create a preview same as the workspace cell size and draw the icon at the 128 // appropriate position. 129 DeviceProfile dp = launcher.getDeviceProfile(); 130 int iconSize = dp.iconSizePx; 131 132 int padding = launcher.getResources() 133 .getDimensionPixelSize(R.dimen.widget_preview_shortcut_padding); 134 previewBounds.left += padding; 135 previewBounds.top += padding; 136 137 dragRegion = new Rect(); 138 dragRegion.left = (mEstimatedCellSize[0] - iconSize) / 2; 139 dragRegion.right = dragRegion.left + iconSize; 140 dragRegion.top = (mEstimatedCellSize[1] 141 - iconSize - dp.iconTextSizePx - dp.iconDrawablePaddingPx) / 2; 142 dragRegion.bottom = dragRegion.top + iconSize; 143 draggableView = DraggableView.ofType(DraggableView.DRAGGABLE_ICON); 144 } 145 146 // Since we are not going through the workspace for starting the drag, set drag related 147 // information on the workspace before starting the drag. 148 launcher.getWorkspace().prepareDragWithProvider(this); 149 150 int dragLayerX = screenPos.x + previewBounds.left 151 + (int) ((scale * preview.getWidth() - preview.getWidth()) / 2); 152 int dragLayerY = screenPos.y + previewBounds.top 153 + (int) ((scale * preview.getHeight() - preview.getHeight()) / 2); 154 155 // Start the drag 156 launcher.getDragController().startDrag(preview, draggableView, dragLayerX, dragLayerY, 157 source, mAddInfo, dragOffset, dragRegion, scale, scale, options); 158 } 159 160 @Override convertPreviewToAlphaBitmap(Bitmap preview)161 protected Bitmap convertPreviewToAlphaBitmap(Bitmap preview) { 162 if (mAddInfo instanceof PendingAddShortcutInfo || mEstimatedCellSize == null) { 163 return super.convertPreviewToAlphaBitmap(preview); 164 } 165 166 int w = mEstimatedCellSize[0]; 167 int h = mEstimatedCellSize[1]; 168 final Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ALPHA_8); 169 Rect src = new Rect(0, 0, preview.getWidth(), preview.getHeight()); 170 171 float scaleFactor = Math.min((w - blurSizeOutline) / (float) preview.getWidth(), 172 (h - blurSizeOutline) / (float) preview.getHeight()); 173 int scaledWidth = (int) (scaleFactor * preview.getWidth()); 174 int scaledHeight = (int) (scaleFactor * preview.getHeight()); 175 Rect dst = new Rect(0, 0, scaledWidth, scaledHeight); 176 177 // center the image 178 dst.offset((w - scaledWidth) / 2, (h - scaledHeight) / 2); 179 new Canvas(b).drawBitmap(preview, src, dst, new Paint(Paint.FILTER_BITMAP_FLAG)); 180 return b; 181 } 182 } 183