Adding support for showing the widget preview based on the provided RemoteViews
Bug: 35811129 Change-Id: I336e48cd00cfec2e617ac73bd8a81419b0944aa7
This commit is contained in:
parent
efd5cbf55c
commit
c65a0085d7
|
@ -36,12 +36,20 @@
|
|||
android:background="?android:attr/colorPrimaryDark"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<include
|
||||
layout="@layout/widget_cell"
|
||||
android:layout_gravity="center_horizontal"
|
||||
<com.android.launcher3.dragndrop.LivePreviewWidgetCell
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/widget_cell" />
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:focusable="true"
|
||||
android:background="?android:attr/colorPrimaryDark"
|
||||
android:gravity="center_horizontal"
|
||||
android:id="@+id/widget_cell"
|
||||
android:layout_gravity="center_horizontal" >
|
||||
|
||||
<include layout="@layout/widget_cell_content" />
|
||||
|
||||
</com.android.launcher3.dragndrop.LivePreviewWidgetCell>
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
|
|
|
@ -23,49 +23,6 @@
|
|||
android:background="?android:attr/colorPrimaryDark"
|
||||
android:gravity="center_horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/widget_preview_label_vertical_padding"
|
||||
android:paddingBottom="@dimen/widget_preview_label_vertical_padding"
|
||||
android:paddingLeft="@dimen/widget_preview_label_horizontal_padding"
|
||||
android:paddingRight="@dimen/widget_preview_label_horizontal_padding"
|
||||
android:orientation="horizontal">
|
||||
<include layout="@layout/widget_cell_content" />
|
||||
|
||||
<!-- The name of the widget. -->
|
||||
<TextView
|
||||
android:id="@+id/widget_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:fadingEdge="horizontal"
|
||||
android:fontFamily="sans-serif-condensed"
|
||||
android:gravity="start"
|
||||
android:singleLine="true"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<!-- The original dimensions of the widget (can't be the same text as above due to different
|
||||
style. -->
|
||||
<TextView
|
||||
android:id="@+id/widget_dims"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="14sp"
|
||||
android:fontFamily="sans-serif-condensed"
|
||||
android:alpha="0.8" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- The image of the widget. This view does not support padding. Any placement adjustment
|
||||
should be done using margins. -->
|
||||
<com.android.launcher3.widget.WidgetImageView
|
||||
android:id="@+id/widget_preview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
</com.android.launcher3.widget.WidgetCell>
|
|
@ -0,0 +1,65 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2017 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/widget_preview_label_vertical_padding"
|
||||
android:paddingBottom="@dimen/widget_preview_label_vertical_padding"
|
||||
android:paddingLeft="@dimen/widget_preview_label_horizontal_padding"
|
||||
android:paddingRight="@dimen/widget_preview_label_horizontal_padding"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<!-- The name of the widget. -->
|
||||
<TextView
|
||||
android:id="@+id/widget_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:fadingEdge="horizontal"
|
||||
android:fontFamily="sans-serif-condensed"
|
||||
android:gravity="start"
|
||||
android:singleLine="true"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<!-- The original dimensions of the widget (can't be the same text as above due to different
|
||||
style. -->
|
||||
<TextView
|
||||
android:id="@+id/widget_dims"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="14sp"
|
||||
android:fontFamily="sans-serif-condensed"
|
||||
android:alpha="0.8" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- The image of the widget. This view does not support padding. Any placement adjustment
|
||||
should be done using margins. -->
|
||||
<com.android.launcher3.widget.WidgetImageView
|
||||
android:id="@+id/widget_preview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
</merge>
|
|
@ -22,6 +22,7 @@ import android.graphics.Rect;
|
|||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.Handler;
|
||||
import android.os.UserHandle;
|
||||
import android.support.v4.graphics.ColorUtils;
|
||||
|
@ -89,14 +90,17 @@ public class WidgetPreviewLoader {
|
|||
*
|
||||
* @return a request id which can be used to cancel the request.
|
||||
*/
|
||||
public PreviewLoadRequest getPreview(WidgetItem item, int previewWidth,
|
||||
public CancellationSignal getPreview(WidgetItem item, int previewWidth,
|
||||
int previewHeight, WidgetCell caller) {
|
||||
String size = previewWidth + "x" + previewHeight;
|
||||
WidgetCacheKey key = new WidgetCacheKey(item.componentName, item.user, size);
|
||||
|
||||
PreviewLoadTask task = new PreviewLoadTask(key, item, previewWidth, previewHeight, caller);
|
||||
task.executeOnExecutor(Utilities.THREAD_POOL_EXECUTOR);
|
||||
return new PreviewLoadRequest(task);
|
||||
|
||||
CancellationSignal signal = new CancellationSignal();
|
||||
signal.setOnCancelListener(task);
|
||||
return signal;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -510,42 +514,8 @@ public class WidgetPreviewLoader {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A request Id which can be used by the client to cancel any request.
|
||||
*/
|
||||
public class PreviewLoadRequest {
|
||||
|
||||
@Thunk final PreviewLoadTask mTask;
|
||||
|
||||
public PreviewLoadRequest(PreviewLoadTask task) {
|
||||
mTask = task;
|
||||
}
|
||||
|
||||
public void cleanup() {
|
||||
if (mTask != null) {
|
||||
mTask.cancel(true);
|
||||
}
|
||||
|
||||
// This only handles the case where the PreviewLoadTask is cancelled after the task has
|
||||
// successfully completed (including having written to disk when necessary). In the
|
||||
// other cases where it is cancelled while the task is running, it will be cleaned up
|
||||
// in the tasks's onCancelled() call, and if cancelled while the task is writing to
|
||||
// disk, it will be cancelled in the task's onPostExecute() call.
|
||||
if (mTask.mBitmapToRecycle != null) {
|
||||
mWorkerHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (mUnusedBitmaps) {
|
||||
mUnusedBitmaps.add(mTask.mBitmapToRecycle);
|
||||
}
|
||||
mTask.mBitmapToRecycle = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class PreviewLoadTask extends AsyncTask<Void, Void, Bitmap> {
|
||||
public class PreviewLoadTask extends AsyncTask<Void, Void, Bitmap>
|
||||
implements CancellationSignal.OnCancelListener {
|
||||
@Thunk final WidgetCacheKey mKey;
|
||||
private final WidgetItem mInfo;
|
||||
private final int mPreviewHeight;
|
||||
|
@ -661,6 +631,28 @@ public class WidgetPreviewLoader {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
cancel(true);
|
||||
|
||||
// This only handles the case where the PreviewLoadTask is cancelled after the task has
|
||||
// successfully completed (including having written to disk when necessary). In the
|
||||
// other cases where it is cancelled while the task is running, it will be cleaned up
|
||||
// in the tasks's onCancelled() call, and if cancelled while the task is writing to
|
||||
// disk, it will be cancelled in the task's onPostExecute() call.
|
||||
if (mBitmapToRecycle != null) {
|
||||
mWorkerHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (mUnusedBitmaps) {
|
||||
mUnusedBitmaps.add(mBitmapToRecycle);
|
||||
}
|
||||
mBitmapToRecycle = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final class WidgetCacheKey extends ComponentKey {
|
||||
|
|
|
@ -76,6 +76,14 @@ public class PinItemRequestCompat implements Parcelable {
|
|||
}
|
||||
}
|
||||
|
||||
public Bundle getExtras() {
|
||||
try {
|
||||
return (Bundle) mObject.getClass().getDeclaredMethod("getExtras").invoke(mObject);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Object invokeMethod(String methodName) {
|
||||
try {
|
||||
return mObject.getClass().getDeclaredMethod(methodName).invoke(mObject);
|
||||
|
|
|
@ -27,10 +27,8 @@ import android.graphics.Canvas;
|
|||
import android.graphics.Point;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.View.*;
|
||||
|
@ -47,7 +45,6 @@ import com.android.launcher3.compat.PinItemRequestCompat;
|
|||
import com.android.launcher3.model.WidgetItem;
|
||||
import com.android.launcher3.shortcuts.ShortcutInfoCompat;
|
||||
import com.android.launcher3.widget.PendingAddWidgetInfo;
|
||||
import com.android.launcher3.widget.WidgetCell;
|
||||
import com.android.launcher3.widget.WidgetHostViewLoader;
|
||||
import com.android.launcher3.widget.WidgetImageView;
|
||||
|
||||
|
@ -65,7 +62,7 @@ public class AddItemActivity extends BaseActivity implements OnLongClickListener
|
|||
private LauncherAppState mApp;
|
||||
private InvariantDeviceProfile mIdp;
|
||||
|
||||
private WidgetCell mWidgetCell;
|
||||
private LivePreviewWidgetCell mWidgetCell;
|
||||
|
||||
// Widget request specific options.
|
||||
private AppWidgetHost mAppWidgetHost;
|
||||
|
@ -92,7 +89,7 @@ public class AddItemActivity extends BaseActivity implements OnLongClickListener
|
|||
mDeviceProfile = mIdp.getDeviceProfile(getApplicationContext());
|
||||
|
||||
setContentView(R.layout.add_item_confirmation_activity);
|
||||
mWidgetCell = (WidgetCell) findViewById(R.id.widget_cell);
|
||||
mWidgetCell = (LivePreviewWidgetCell) findViewById(R.id.widget_cell);
|
||||
|
||||
if (mRequest.getRequestType() == PinItemRequestCompat.REQUEST_TYPE_SHORTCUT) {
|
||||
setupShortcut();
|
||||
|
@ -169,6 +166,7 @@ public class AddItemActivity extends BaseActivity implements OnLongClickListener
|
|||
// Cannot add widget
|
||||
return false;
|
||||
}
|
||||
mWidgetCell.setPreview(PinItemDragListener.getPreview(mRequest));
|
||||
|
||||
mAppWidgetManager = AppWidgetManagerCompat.getInstance(this);
|
||||
mAppWidgetHost = new AppWidgetHost(this, Launcher.APPWIDGET_HOST_ID);
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
package com.android.launcher3.dragndrop;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
import com.android.launcher3.BaseActivity;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.LauncherAppWidgetProviderInfo;
|
||||
import com.android.launcher3.widget.WidgetCell;
|
||||
|
||||
/**
|
||||
* Extension of {@link WidgetCell} which supports generating previews from {@link RemoteViews}
|
||||
*/
|
||||
public class LivePreviewWidgetCell extends WidgetCell {
|
||||
|
||||
private RemoteViews mPreview;
|
||||
|
||||
public LivePreviewWidgetCell(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public LivePreviewWidgetCell(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public LivePreviewWidgetCell(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public void setPreview(RemoteViews view) {
|
||||
mPreview = view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ensurePreview() {
|
||||
if (mPreview != null && mActiveRequest == null) {
|
||||
Bitmap preview = generateFromRemoteViews(
|
||||
mActivity, mPreview, mItem.widgetInfo, mPresetPreviewSize, new int[1]);
|
||||
if (preview != null) {
|
||||
applyPreview(preview);
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.ensurePreview();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a bitmap by inflating {@param views}.
|
||||
* @see com.android.launcher3.WidgetPreviewLoader#generateWidgetPreview
|
||||
*
|
||||
* TODO: Consider moving this to the background thread.
|
||||
*/
|
||||
public static Bitmap generateFromRemoteViews(BaseActivity activity, RemoteViews views,
|
||||
LauncherAppWidgetProviderInfo info, int previewSize, int[] preScaledWidthOut) {
|
||||
|
||||
DeviceProfile dp = activity.getDeviceProfile();
|
||||
int viewWidth = dp.cellWidthPx * info.spanX;
|
||||
int viewHeight = dp.cellHeightPx * info.spanY;
|
||||
|
||||
final View v;
|
||||
try {
|
||||
v = views.apply(activity, new FrameLayout(activity));
|
||||
v.measure(MeasureSpec.makeMeasureSpec(viewWidth, MeasureSpec.EXACTLY),
|
||||
MeasureSpec.makeMeasureSpec(viewHeight, MeasureSpec.EXACTLY));
|
||||
|
||||
viewWidth = v.getMeasuredWidth();
|
||||
viewHeight = v.getMeasuredHeight();
|
||||
v.layout(0, 0, viewWidth, viewHeight);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
preScaledWidthOut[0] = viewWidth;
|
||||
final int bitmapWidth, bitmapHeight;
|
||||
final float scale;
|
||||
if (viewWidth > previewSize) {
|
||||
scale = ((float) previewSize) / viewWidth;
|
||||
bitmapWidth = previewSize;
|
||||
bitmapHeight = (int) (viewHeight * scale);
|
||||
} else {
|
||||
scale = 1;
|
||||
bitmapWidth = viewWidth;
|
||||
bitmapHeight = viewHeight;
|
||||
}
|
||||
|
||||
Bitmap preview = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
|
||||
Canvas c = new Canvas(preview);
|
||||
c.scale(scale, scale);
|
||||
v.draw(c);
|
||||
c.setBitmap(null);
|
||||
return preview;
|
||||
}
|
||||
}
|
|
@ -16,9 +16,11 @@
|
|||
|
||||
package com.android.launcher3.dragndrop;
|
||||
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.content.ClipDescription;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Parcel;
|
||||
|
@ -27,6 +29,7 @@ import android.os.SystemClock;
|
|||
import android.util.Log;
|
||||
import android.view.DragEvent;
|
||||
import android.view.View;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
import com.android.launcher3.DeleteDropTarget;
|
||||
import com.android.launcher3.DragSource;
|
||||
|
@ -171,7 +174,12 @@ public class PinItemDragListener
|
|||
// and the absolute position (position relative to the screen) of drag event is same
|
||||
// across windows, using drag position here give a good estimate for relative position
|
||||
// to source window.
|
||||
new PendingItemDragHelper(view).startDrag(new Rect(mPreviewRect),
|
||||
PendingItemDragHelper dragHelper = new PendingItemDragHelper(view);
|
||||
if (mRequest.getRequestType() == PinItemRequestCompat.REQUEST_TYPE_APPWIDGET) {
|
||||
dragHelper.setPreview(getPreview(mRequest));
|
||||
}
|
||||
|
||||
dragHelper.startDrag(new Rect(mPreviewRect),
|
||||
mPreviewBitmapWidth, mPreviewViewWidth, downPos, this, options);
|
||||
mDragStartTime = SystemClock.uptimeMillis();
|
||||
return true;
|
||||
|
@ -250,6 +258,15 @@ public class PinItemDragListener
|
|||
}
|
||||
}
|
||||
|
||||
public static RemoteViews getPreview(PinItemRequestCompat request) {
|
||||
Bundle extras = request.getExtras();
|
||||
if (extras != null &&
|
||||
extras.get(AppWidgetManager.EXTRA_APPWIDGET_PREVIEW) instanceof RemoteViews) {
|
||||
return (RemoteViews) extras.get(AppWidgetManager.EXTRA_APPWIDGET_PREVIEW);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<PinItemDragListener> CREATOR =
|
||||
new Parcelable.Creator<PinItemDragListener>() {
|
||||
public PinItemDragListener createFromParcel(Parcel source) {
|
||||
|
|
|
@ -23,6 +23,7 @@ import android.graphics.Point;
|
|||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.View;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.DragSource;
|
||||
|
@ -32,6 +33,7 @@ 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;
|
||||
|
@ -47,12 +49,17 @@ public class PendingItemDragHelper extends DragPreviewProvider {
|
|||
private final PendingAddItemInfo mAddInfo;
|
||||
|
||||
private Bitmap mPreviewBitmap;
|
||||
private RemoteViews mPreview;
|
||||
|
||||
public PendingItemDragHelper(View view) {
|
||||
super(view);
|
||||
mAddInfo = (PendingAddItemInfo) view.getTag();
|
||||
}
|
||||
|
||||
public void setPreview(RemoteViews preview) {
|
||||
mPreview = preview;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the drag for the pending item associated with the view.
|
||||
*
|
||||
|
@ -67,7 +74,7 @@ public class PendingItemDragHelper extends DragPreviewProvider {
|
|||
final Launcher launcher = Launcher.getLauncher(mView.getContext());
|
||||
LauncherAppState app = LauncherAppState.getInstance(launcher);
|
||||
|
||||
final Bitmap preview;
|
||||
Bitmap preview = null;
|
||||
final float scale;
|
||||
final Point dragOffset;
|
||||
final Rect dragRegion;
|
||||
|
@ -80,8 +87,15 @@ public class PendingItemDragHelper extends DragPreviewProvider {
|
|||
int maxWidth = Math.min((int) (previewBitmapWidth * MAX_WIDGET_SCALE), size[0]);
|
||||
|
||||
int[] previewSizeBeforeScale = new int[1];
|
||||
preview = app.getWidgetCache() .generateWidgetPreview(
|
||||
launcher, createWidgetInfo.info, maxWidth, null, previewSizeBeforeScale);
|
||||
|
||||
if (mPreview != null) {
|
||||
preview = LivePreviewWidgetCell.generateFromRemoteViews(launcher, mPreview,
|
||||
createWidgetInfo.info, maxWidth, previewSizeBeforeScale);
|
||||
}
|
||||
if (preview == null) {
|
||||
preview = app.getWidgetCache().generateWidgetPreview(
|
||||
launcher, createWidgetInfo.info, maxWidth, null, previewSizeBeforeScale);
|
||||
}
|
||||
|
||||
if (previewSizeBeforeScale[0] < previewBitmapWidth) {
|
||||
// The icon has extra padding around it.
|
||||
|
|
|
@ -18,6 +18,7 @@ package com.android.launcher3.widget;
|
|||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.CancellationSignal;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
|
@ -34,7 +35,6 @@ import com.android.launcher3.R;
|
|||
import com.android.launcher3.SimpleOnStylusPressListener;
|
||||
import com.android.launcher3.StylusEventHelper;
|
||||
import com.android.launcher3.WidgetPreviewLoader;
|
||||
import com.android.launcher3.WidgetPreviewLoader.PreviewLoadRequest;
|
||||
import com.android.launcher3.graphics.DrawableFactory;
|
||||
import com.android.launcher3.model.WidgetItem;
|
||||
|
||||
|
@ -60,20 +60,21 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
|
|||
/** Widget preview width is calculated by multiplying this factor to the widget cell width. */
|
||||
private static final float PREVIEW_SCALE = 0.8f;
|
||||
|
||||
private int mPresetPreviewSize;
|
||||
protected int mPresetPreviewSize;
|
||||
private int mCellSize;
|
||||
|
||||
private WidgetImageView mWidgetImage;
|
||||
private TextView mWidgetName;
|
||||
private TextView mWidgetDims;
|
||||
|
||||
private WidgetItem mItem;
|
||||
protected WidgetItem mItem;
|
||||
|
||||
private WidgetPreviewLoader mWidgetPreviewLoader;
|
||||
private PreviewLoadRequest mActiveRequest;
|
||||
private StylusEventHelper mStylusEventHelper;
|
||||
|
||||
private final BaseActivity mActivity;
|
||||
protected CancellationSignal mActiveRequest;
|
||||
|
||||
protected final BaseActivity mActivity;
|
||||
|
||||
public WidgetCell(Context context) {
|
||||
this(context, null);
|
||||
|
@ -123,7 +124,7 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
|
|||
mWidgetDims.setText(null);
|
||||
|
||||
if (mActiveRequest != null) {
|
||||
mActiveRequest.cleanup();
|
||||
mActiveRequest.cancel();
|
||||
mActiveRequest = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#FFFF00">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_margin="20dp"
|
||||
android:background="#FF0000"
|
||||
android:id="@android:id/icon" />
|
||||
</FrameLayout>
|
|
@ -28,6 +28,7 @@ import android.graphics.Color;
|
|||
import android.graphics.Paint;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.os.Bundle;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
/**
|
||||
* Sample activity to request pinning an item.
|
||||
|
@ -36,7 +37,8 @@ import android.os.Bundle;
|
|||
public class RequestPinItemActivity extends BaseTestingActivity {
|
||||
|
||||
private PendingIntent mCallback = null;
|
||||
private String mShortcutId;
|
||||
private String mShortcutId = "test-id";
|
||||
private int mRemoteViewColor = Color.TRANSPARENT;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
@ -51,6 +53,10 @@ public class RequestPinItemActivity extends BaseTestingActivity {
|
|||
mCallback = callback;
|
||||
}
|
||||
|
||||
public void setRemoteViewColor(int color) {
|
||||
mRemoteViewColor = color;
|
||||
}
|
||||
|
||||
public void setShortcutId(String id) {
|
||||
mShortcutId = id;
|
||||
}
|
||||
|
@ -84,6 +90,16 @@ public class RequestPinItemActivity extends BaseTestingActivity {
|
|||
}
|
||||
|
||||
private void requestWidget(ComponentName cn) {
|
||||
AppWidgetManager.getInstance(this).requestPinAppWidget(cn, null, mCallback);
|
||||
Bundle extras = null;
|
||||
if (mRemoteViewColor != Color.TRANSPARENT) {
|
||||
int layoutId = getResources().getIdentifier(
|
||||
"test_layout_appwidget_view", "layout", getPackageName());
|
||||
RemoteViews views = new RemoteViews(getPackageName(), layoutId);
|
||||
views.setInt(android.R.id.icon, "setBackgroundColor", mRemoteViewColor);
|
||||
extras = new Bundle();
|
||||
extras.putParcelable(AppWidgetManager.EXTRA_APPWIDGET_PREVIEW, views);
|
||||
}
|
||||
|
||||
AppWidgetManager.getInstance(this).requestPinAppWidget(cn, extras, mCallback);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import android.app.Application;
|
|||
import android.app.PendingIntent;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.support.test.uiautomator.By;
|
||||
import android.support.test.uiautomator.UiObject2;
|
||||
import android.support.test.uiautomator.Until;
|
||||
|
@ -95,6 +96,23 @@ public class RequestPinItemTest extends LauncherInstrumentationTestCase {
|
|||
});
|
||||
}
|
||||
|
||||
public void testPinWidgetNoConfig_customPreview() throws Throwable {
|
||||
// Command to set custom preview
|
||||
Intent command = RequestPinItemActivity.getCommandIntent(
|
||||
RequestPinItemActivity.class, "setRemoteViewColor").putExtra(
|
||||
RequestPinItemActivity.EXTRA_PARAM + "0", Color.RED);
|
||||
|
||||
runTest("pinWidgetNoConfig", true, new ItemOperator() {
|
||||
@Override
|
||||
public boolean evaluate(ItemInfo info, View view) {
|
||||
return info instanceof LauncherAppWidgetInfo &&
|
||||
((LauncherAppWidgetInfo) info).appWidgetId == mAppWidgetId &&
|
||||
((LauncherAppWidgetInfo) info).providerName.getClassName()
|
||||
.equals(AppWidgetNoConfig.class.getName());
|
||||
}
|
||||
}, command);
|
||||
}
|
||||
|
||||
public void testPinWidgetWithConfig() throws Throwable {
|
||||
runTest("pinWidgetWithConfig", true, new ItemOperator() {
|
||||
@Override
|
||||
|
@ -107,8 +125,12 @@ public class RequestPinItemTest extends LauncherInstrumentationTestCase {
|
|||
});
|
||||
}
|
||||
|
||||
public void testPinShortcut() throws Throwable {
|
||||
// Command to set the shortcut id
|
||||
Intent command = RequestPinItemActivity.getCommandIntent(
|
||||
RequestPinItemActivity.class, "setShortcutId").putExtra(
|
||||
RequestPinItemActivity.EXTRA_PARAM + "0", mShortcutId);
|
||||
|
||||
public void testPinWidgetShortcut() throws Throwable {
|
||||
runTest("pinShortcut", false, new ItemOperator() {
|
||||
@Override
|
||||
public boolean evaluate(ItemInfo info, View view) {
|
||||
|
@ -116,11 +138,11 @@ public class RequestPinItemTest extends LauncherInstrumentationTestCase {
|
|||
info.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT &&
|
||||
ShortcutKey.fromItemInfo(info).getId().equals(mShortcutId);
|
||||
}
|
||||
});
|
||||
}, command);
|
||||
}
|
||||
|
||||
private void runTest(String activityMethod, boolean isWidget, ItemOperator itemMatcher)
|
||||
throws Throwable {
|
||||
private void runTest(String activityMethod, boolean isWidget, ItemOperator itemMatcher,
|
||||
Intent... commandIntents) throws Throwable {
|
||||
if (!Utilities.isAtLeastO()) {
|
||||
return;
|
||||
}
|
||||
|
@ -146,11 +168,8 @@ public class RequestPinItemTest extends LauncherInstrumentationTestCase {
|
|||
RequestPinItemActivity.class, "setCallback").putExtra(
|
||||
RequestPinItemActivity.EXTRA_PARAM + "0", callback));
|
||||
|
||||
if (!isWidget) {
|
||||
// Set shortcut id
|
||||
mTargetContext.sendBroadcast(RequestPinItemActivity.getCommandIntent(
|
||||
RequestPinItemActivity.class, "setShortcutId").putExtra(
|
||||
RequestPinItemActivity.EXTRA_PARAM + "0", mShortcutId));
|
||||
for (Intent command : commandIntents) {
|
||||
mTargetContext.sendBroadcast(command);
|
||||
}
|
||||
|
||||
// call the requested method to start the flow
|
||||
|
|
Loading…
Reference in New Issue