1 package com.android.launcher3.dragndrop;
2 
3 import android.content.Context;
4 import android.graphics.Bitmap;
5 import android.graphics.Canvas;
6 import android.util.AttributeSet;
7 import android.view.View;
8 import android.widget.FrameLayout;
9 import android.widget.RemoteViews;
10 
11 import com.android.launcher3.BaseActivity;
12 import com.android.launcher3.DeviceProfile;
13 import com.android.launcher3.LauncherAppWidgetProviderInfo;
14 import com.android.launcher3.widget.WidgetCell;
15 
16 /**
17  * Extension of {@link WidgetCell} which supports generating previews from {@link RemoteViews}
18  */
19 public class LivePreviewWidgetCell extends WidgetCell {
20 
21     private RemoteViews mPreview;
22 
LivePreviewWidgetCell(Context context)23     public LivePreviewWidgetCell(Context context) {
24         this(context, null);
25     }
26 
LivePreviewWidgetCell(Context context, AttributeSet attrs)27     public LivePreviewWidgetCell(Context context, AttributeSet attrs) {
28         this(context, attrs, 0);
29     }
30 
LivePreviewWidgetCell(Context context, AttributeSet attrs, int defStyle)31     public LivePreviewWidgetCell(Context context, AttributeSet attrs, int defStyle) {
32         super(context, attrs, defStyle);
33     }
34 
setPreview(RemoteViews view)35     public void setPreview(RemoteViews view) {
36         mPreview = view;
37     }
38 
39     @Override
ensurePreview()40     public void ensurePreview() {
41         if (mPreview != null && mActiveRequest == null) {
42             Bitmap preview = generateFromRemoteViews(
43                     mActivity, mPreview, mItem.widgetInfo, mPresetPreviewSize, new int[1]);
44             if (preview != null) {
45                 applyPreview(preview);
46                 return;
47             }
48         }
49         super.ensurePreview();
50     }
51 
52     /**
53      * Generates a bitmap by inflating {@param views}.
54      * @see com.android.launcher3.WidgetPreviewLoader#generateWidgetPreview
55      *
56      * TODO: Consider moving this to the background thread.
57      */
generateFromRemoteViews(BaseActivity activity, RemoteViews views, LauncherAppWidgetProviderInfo info, int previewSize, int[] preScaledWidthOut)58     public static Bitmap generateFromRemoteViews(BaseActivity activity, RemoteViews views,
59             LauncherAppWidgetProviderInfo info, int previewSize, int[] preScaledWidthOut) {
60 
61         DeviceProfile dp = activity.getDeviceProfile();
62         int viewWidth = dp.cellWidthPx * info.spanX;
63         int viewHeight = dp.cellHeightPx * info.spanY;
64 
65         final View v;
66         try {
67             v = views.apply(activity, new FrameLayout(activity));
68             v.measure(MeasureSpec.makeMeasureSpec(viewWidth, MeasureSpec.EXACTLY),
69                     MeasureSpec.makeMeasureSpec(viewHeight, MeasureSpec.EXACTLY));
70 
71             viewWidth = v.getMeasuredWidth();
72             viewHeight = v.getMeasuredHeight();
73             v.layout(0, 0, viewWidth, viewHeight);
74         } catch (Exception e) {
75             return null;
76         }
77 
78         preScaledWidthOut[0] = viewWidth;
79         final int bitmapWidth, bitmapHeight;
80         final float scale;
81         if (viewWidth > previewSize) {
82             scale = ((float) previewSize) / viewWidth;
83             bitmapWidth = previewSize;
84             bitmapHeight = (int) (viewHeight * scale);
85         } else {
86             scale = 1;
87             bitmapWidth = viewWidth;
88             bitmapHeight = viewHeight;
89         }
90 
91         Bitmap preview = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
92         Canvas c = new Canvas(preview);
93         c.scale(scale, scale);
94         v.draw(c);
95         c.setBitmap(null);
96         return preview;
97     }
98 }
99