Merge "Render RemoteViews in LauncherAppWidgetHostView" into sc-dev

This commit is contained in:
Steven Ng 2021-04-21 16:40:05 +00:00 committed by Android (Google) Code Review
commit 6f944f3624
4 changed files with 71 additions and 85 deletions

View File

@ -59,6 +59,7 @@ import com.android.launcher3.pm.PinRequestHelper;
import com.android.launcher3.views.BaseDragLayer; import com.android.launcher3.views.BaseDragLayer;
import com.android.launcher3.widget.LauncherAppWidgetHost; import com.android.launcher3.widget.LauncherAppWidgetHost;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo; import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.NavigableAppWidgetHostView;
import com.android.launcher3.widget.PendingAddShortcutInfo; import com.android.launcher3.widget.PendingAddShortcutInfo;
import com.android.launcher3.widget.PendingAddWidgetInfo; import com.android.launcher3.widget.PendingAddWidgetInfo;
import com.android.launcher3.widget.WidgetCell; import com.android.launcher3.widget.WidgetCell;
@ -147,20 +148,31 @@ public class AddItemActivity extends BaseActivity implements OnLongClickListener
public boolean onLongClick(View view) { public boolean onLongClick(View view) {
// Find the position of the preview relative to the touch location. // Find the position of the preview relative to the touch location.
WidgetImageView img = mWidgetCell.getWidgetView(); WidgetImageView img = mWidgetCell.getWidgetView();
NavigableAppWidgetHostView appWidgetHostView = mWidgetCell.getAppWidgetHostViewPreview();
// If the ImageView doesn't have a drawable yet, the widget preview hasn't been loaded and // If the ImageView doesn't have a drawable yet, the widget preview hasn't been loaded and
// we abort the drag. // we abort the drag.
if (img.getDrawable() == null) { if (img.getDrawable() == null && appWidgetHostView == null) {
return false; return false;
} }
Rect bounds = img.getBitmapBounds(); final Rect bounds;
bounds.offset(img.getLeft() - (int) mLastTouchPos.x, img.getTop() - (int) mLastTouchPos.y);
// Start home and pass the draw request params // Start home and pass the draw request params
PinItemDragListener listener = new PinItemDragListener(mRequest, bounds, final PinItemDragListener listener;
img.getDrawable().getIntrinsicWidth(), img.getWidth()); if (appWidgetHostView != null) {
bounds = new Rect();
appWidgetHostView.getSourceVisualDragBounds(bounds);
bounds.offset(appWidgetHostView.getLeft() - (int) mLastTouchPos.x,
appWidgetHostView.getTop() - (int) mLastTouchPos.y);
listener = new PinItemDragListener(mRequest, bounds,
appWidgetHostView.getMeasuredWidth(), appWidgetHostView.getMeasuredWidth());
} else {
bounds = img.getBitmapBounds();
bounds.offset(img.getLeft() - (int) mLastTouchPos.x,
img.getTop() - (int) mLastTouchPos.y);
listener = new PinItemDragListener(mRequest, bounds,
img.getDrawable().getIntrinsicWidth(), img.getWidth());
}
// Start a system drag and drop. We use a transparent bitmap as preview for system drag // Start a system drag and drop. We use a transparent bitmap as preview for system drag
// as the preview is handled internally by launcher. // as the preview is handled internally by launcher.
@ -214,7 +226,7 @@ public class AddItemActivity extends BaseActivity implements OnLongClickListener
// Cannot add widget // Cannot add widget
return false; return false;
} }
mWidgetCell.setPreview(PinItemDragListener.getPreview(mRequest)); mWidgetCell.setRemoteViewsPreview(PinItemDragListener.getPreview(mRequest));
mAppWidgetManager = new WidgetManagerHelper(this); mAppWidgetManager = new WidgetManagerHelper(this);
mAppWidgetHost = new LauncherAppWidgetHost(this); mAppWidgetHost = new LauncherAppWidgetHost(this);
@ -238,6 +250,7 @@ public class AddItemActivity extends BaseActivity implements OnLongClickListener
@Override @Override
protected void onPostExecute(WidgetItem item) { protected void onPostExecute(WidgetItem item) {
mWidgetCell.setPreviewSize(item.spanX, item.spanY);
mWidgetCell.applyFromCellItem(item, mApp.getWidgetCache()); mWidgetCell.applyFromCellItem(item, mApp.getWidgetCache());
mWidgetCell.ensurePreview(); mWidgetCell.ensurePreview();
} }

View File

@ -114,7 +114,7 @@ public abstract class BaseWidgetSheet extends AbstractSlideInView
} }
PendingItemDragHelper dragHelper = new PendingItemDragHelper(v); PendingItemDragHelper dragHelper = new PendingItemDragHelper(v);
dragHelper.setRemoteViewsPreview(v.getPreview()); dragHelper.setRemoteViewsPreview(v.getRemoteViewsPreview());
dragHelper.setAppWidgetHostViewPreview(v.getAppWidgetHostViewPreview()); dragHelper.setAppWidgetHostViewPreview(v.getAppWidgetHostViewPreview());
if (image.getDrawable() != null) { if (image.getDrawable() != null) {

View File

@ -23,6 +23,7 @@ import android.graphics.Point;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.view.View; import android.view.View;
import android.view.View.MeasureSpec;
import android.widget.RemoteViews; import android.widget.RemoteViews;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@ -53,7 +54,7 @@ public class PendingItemDragHelper extends DragPreviewProvider {
private int[] mEstimatedCellSize; private int[] mEstimatedCellSize;
@Nullable private RemoteViews mRemoteViewsPreview; @Nullable private RemoteViews mRemoteViewsPreview;
@Nullable private LauncherAppWidgetHostView mAppWidgetHostViewPreview; @Nullable private NavigableAppWidgetHostView mAppWidgetHostViewPreview;
private final float mEnforcedRoundedCornersForWidget; private final float mEnforcedRoundedCornersForWidget;
public PendingItemDragHelper(View view) { public PendingItemDragHelper(View view) {
@ -71,9 +72,9 @@ public class PendingItemDragHelper extends DragPreviewProvider {
mRemoteViewsPreview = remoteViewsPreview; mRemoteViewsPreview = remoteViewsPreview;
} }
/** Sets a {@link LauncherAppWidgetHostView} which shows a preview layout of an app widget. */ /** Sets a {@link NavigableAppWidgetHostView} which shows a preview layout of an app widget. */
public void setAppWidgetHostViewPreview( public void setAppWidgetHostViewPreview(
@Nullable LauncherAppWidgetHostView appWidgetHostViewPreview) { @Nullable NavigableAppWidgetHostView appWidgetHostViewPreview) {
mAppWidgetHostViewPreview = appWidgetHostViewPreview; mAppWidgetHostViewPreview = appWidgetHostViewPreview;
} }
@ -110,9 +111,22 @@ public class PendingItemDragHelper extends DragPreviewProvider {
int[] previewSizeBeforeScale = new int[1]; int[] previewSizeBeforeScale = new int[1];
if (mRemoteViewsPreview != null) { if (mRemoteViewsPreview != null) {
preview = new FastBitmapDrawable( mAppWidgetHostViewPreview = new LauncherAppWidgetHostView(launcher);
WidgetCell.generateFromRemoteViews(launcher, mRemoteViewsPreview, mAppWidgetHostViewPreview.setAppWidget(/* appWidgetId= */ -1,
createWidgetInfo.info, maxWidth, previewSizeBeforeScale)); ((PendingAddWidgetInfo) mAddInfo).info);
DeviceProfile deviceProfile = launcher.getDeviceProfile();
Rect padding = new Rect();
mAppWidgetHostViewPreview.getWidgetInset(deviceProfile, padding);
mAppWidgetHostViewPreview.setPadding(padding.left, padding.top, padding.right,
padding.bottom);
mAppWidgetHostViewPreview.updateAppWidget(/* remoteViews= */ mRemoteViewsPreview);
int width =
deviceProfile.cellWidthPx * mAddInfo.spanX + padding.left + padding.right;
int height =
deviceProfile.cellHeightPx * mAddInfo.spanY + padding.top + padding.bottom;
mAppWidgetHostViewPreview.measure(
MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
} }
if (mAppWidgetHostViewPreview != null) { if (mAppWidgetHostViewPreview != null) {
previewSizeBeforeScale[0] = mAppWidgetHostViewPreview.getMeasuredWidth(); previewSizeBeforeScale[0] = mAppWidgetHostViewPreview.getMeasuredWidth();

View File

@ -46,7 +46,6 @@ import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R; import com.android.launcher3.R;
import com.android.launcher3.WidgetPreviewLoader; import com.android.launcher3.WidgetPreviewLoader;
import com.android.launcher3.icons.BaseIconFactory; import com.android.launcher3.icons.BaseIconFactory;
import com.android.launcher3.icons.BitmapRenderer;
import com.android.launcher3.icons.FastBitmapDrawable; import com.android.launcher3.icons.FastBitmapDrawable;
import com.android.launcher3.icons.RoundDrawableWrapper; import com.android.launcher3.icons.RoundDrawableWrapper;
import com.android.launcher3.model.WidgetItem; import com.android.launcher3.model.WidgetItem;
@ -100,8 +99,8 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
private final CheckLongPressHelper mLongPressHelper; private final CheckLongPressHelper mLongPressHelper;
private final float mEnforcedCornerRadius; private final float mEnforcedCornerRadius;
private RemoteViews mPreview; private RemoteViews mRemoteViewsPreview;
private LauncherAppWidgetHostView mAppWidgetHostViewPreview; private NavigableAppWidgetHostView mAppWidgetHostViewPreview;
public WidgetCell(Context context) { public WidgetCell(Context context) {
this(context, null); this(context, null);
@ -143,12 +142,13 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
mWidgetDescription = findViewById(R.id.widget_description); mWidgetDescription = findViewById(R.id.widget_description);
} }
public void setPreview(RemoteViews view) { public void setRemoteViewsPreview(RemoteViews view) {
mPreview = view; mRemoteViewsPreview = view;
} }
public RemoteViews getPreview() { @Nullable
return mPreview; public RemoteViews getRemoteViewsPreview() {
return mRemoteViewsPreview;
} }
/** /**
@ -172,7 +172,7 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
mActiveRequest.cancel(); mActiveRequest.cancel();
mActiveRequest = null; mActiveRequest = null;
} }
mPreview = null; mRemoteViewsPreview = null;
if (mAppWidgetHostViewPreview != null) { if (mAppWidgetHostViewPreview != null) {
mWidgetImageContainer.removeView(mAppWidgetHostViewPreview); mWidgetImageContainer.removeView(mAppWidgetHostViewPreview);
} }
@ -180,7 +180,7 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
} }
public void applyFromCellItem(WidgetItem item, WidgetPreviewLoader loader) { public void applyFromCellItem(WidgetItem item, WidgetPreviewLoader loader) {
applyPreviewLayout(item); applyPreviewOnAppWidgetHostView(item);
mItem = item; mItem = item;
mWidgetName.setText(mItem.label); mWidgetName.setText(mItem.label);
@ -206,9 +206,26 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
} }
} }
private void applyPreviewLayout(WidgetItem item) {
private void applyPreviewOnAppWidgetHostView(WidgetItem item) {
if (mRemoteViewsPreview != null) {
mAppWidgetHostViewPreview = new NavigableAppWidgetHostView(getContext()) {
@Override
protected boolean shouldAllowDirectClick() {
return false;
}
};
mAppWidgetHostViewPreview.setAppWidget(/* appWidgetId= */ -1, item.widgetInfo);
Rect padding = new Rect();
mAppWidgetHostViewPreview.getWidgetInset(mActivity.getDeviceProfile(), padding);
mAppWidgetHostViewPreview.setPadding(padding.left, padding.top, padding.right,
padding.bottom);
mAppWidgetHostViewPreview.updateAppWidget(/* remoteViews= */ mRemoteViewsPreview);
return;
}
if (ATLEAST_S if (ATLEAST_S
&& mPreview == null && mRemoteViewsPreview == null
&& item.widgetInfo != null && item.widgetInfo != null
&& item.widgetInfo.previewLayout != Resources.ID_NULL) { && item.widgetInfo.previewLayout != Resources.ID_NULL) {
mAppWidgetHostViewPreview = new LauncherAppWidgetHostView(getContext()); mAppWidgetHostViewPreview = new LauncherAppWidgetHostView(getContext());
@ -234,7 +251,7 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
} }
@Nullable @Nullable
public LauncherAppWidgetHostView getAppWidgetHostViewPreview() { public NavigableAppWidgetHostView getAppWidgetHostViewPreview() {
return mAppWidgetHostViewPreview; return mAppWidgetHostViewPreview;
} }
@ -303,15 +320,6 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
} }
public void ensurePreview() { public void ensurePreview() {
if (mPreview != null && mActiveRequest == null) {
Bitmap preview = generateFromRemoteViews(
mActivity, mPreview, mItem.widgetInfo, mPresetPreviewSize, new int[1]);
if (preview != null) {
applyPreview(new FastBitmapDrawable(preview));
return;
}
}
if (mAppWidgetHostViewPreview != null) { if (mAppWidgetHostViewPreview != null) {
setContainerSize(mPreviewWidth, mPreviewHeight); setContainerSize(mPreviewWidth, mPreviewHeight);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
@ -385,53 +393,4 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
super.onInitializeAccessibilityNodeInfo(info); super.onInitializeAccessibilityNodeInfo(info);
info.removeAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK); info.removeAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK);
} }
/**
* 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) {
try {
return generateFromView(activity, views.apply(activity, new FrameLayout(activity)),
info, previewSize, preScaledWidthOut);
} catch (Exception e) {
return null;
}
}
private static Bitmap generateFromView(BaseActivity activity, View v,
LauncherAppWidgetProviderInfo info, int previewSize, int[] preScaledWidthOut) {
DeviceProfile dp = activity.getDeviceProfile();
int viewWidth = dp.cellWidthPx * info.spanX;
int viewHeight = dp.cellHeightPx * info.spanY;
v.measure(MeasureSpec.makeMeasureSpec(viewWidth, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(viewHeight, MeasureSpec.EXACTLY));
viewWidth = v.getMeasuredWidth();
viewHeight = v.getMeasuredHeight();
v.layout(0, 0, viewWidth, viewHeight);
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;
}
return BitmapRenderer.createSoftwareBitmap(bitmapWidth, bitmapHeight, c -> {
c.scale(scale, scale);
v.draw(c);
});
}
} }