Merge "Refactoring PinItemDragListener into a base class to allow diffenret implementations of multi-window drag and drop" into ub-launcher3-dorval-polish
This commit is contained in:
committed by
Android (Google) Code Review
commit
7a4d1f4383
@@ -217,6 +217,10 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
|
||||
return info == null ? null : (ShortcutInfo) info.getItemInfo().first;
|
||||
}
|
||||
|
||||
public static ShortcutInfo fromActivityInfo(LauncherActivityInfo info, Context context) {
|
||||
return (ShortcutInfo) (new PendingInstallShortcutInfo(info, context).getItemInfo().first);
|
||||
}
|
||||
|
||||
public static void queueShortcut(ShortcutInfoCompat info, Context context) {
|
||||
queuePendingShortcutInfo(new PendingInstallShortcutInfo(info, context), context);
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ public abstract class ShortcutConfigActivityInfo {
|
||||
}
|
||||
|
||||
@TargetApi(26)
|
||||
static class ShortcutConfigActivityInfoVO extends ShortcutConfigActivityInfo {
|
||||
public static class ShortcutConfigActivityInfoVO extends ShortcutConfigActivityInfo {
|
||||
|
||||
private final LauncherActivityInfo mInfo;
|
||||
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.android.launcher3.dragndrop;
|
||||
|
||||
import android.content.ClipDescription;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Parcel;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
import android.view.DragEvent;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.DeleteDropTarget;
|
||||
import com.android.launcher3.DragSource;
|
||||
import com.android.launcher3.DropTarget;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.folder.Folder;
|
||||
import com.android.launcher3.widget.PendingItemDragHelper;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* {@link DragSource} for handling drop from a different window.
|
||||
*/
|
||||
public abstract class BaseItemDragListener implements
|
||||
View.OnDragListener, DragSource, DragOptions.PreDragCondition {
|
||||
|
||||
private static final String TAG = "BaseItemDragListener";
|
||||
|
||||
private static final String MIME_TYPE_PREFIX = "com.android.launcher3.drag_and_drop/";
|
||||
public static final String EXTRA_PIN_ITEM_DRAG_LISTENER = "pin_item_drag_listener";
|
||||
|
||||
// Position of preview relative to the touch location
|
||||
private final Rect mPreviewRect;
|
||||
|
||||
private final int mPreviewBitmapWidth;
|
||||
private final int mPreviewViewWidth;
|
||||
|
||||
// Randomly generated id used to verify the drag event.
|
||||
private final String mId;
|
||||
|
||||
protected Launcher mLauncher;
|
||||
private DragController mDragController;
|
||||
private long mDragStartTime;
|
||||
|
||||
public BaseItemDragListener(Rect previewRect, int previewBitmapWidth, int previewViewWidth) {
|
||||
mPreviewRect = previewRect;
|
||||
mPreviewBitmapWidth = previewBitmapWidth;
|
||||
mPreviewViewWidth = previewViewWidth;
|
||||
mId = UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
protected BaseItemDragListener(Parcel parcel) {
|
||||
mPreviewRect = Rect.CREATOR.createFromParcel(parcel);
|
||||
mPreviewBitmapWidth = parcel.readInt();
|
||||
mPreviewViewWidth = parcel.readInt();
|
||||
mId = parcel.readString();
|
||||
}
|
||||
|
||||
protected void writeToParcel(Parcel parcel, int i) {
|
||||
mPreviewRect.writeToParcel(parcel, i);
|
||||
parcel.writeInt(mPreviewBitmapWidth);
|
||||
parcel.writeInt(mPreviewViewWidth);
|
||||
parcel.writeString(mId);
|
||||
}
|
||||
|
||||
public String getMimeType() {
|
||||
return MIME_TYPE_PREFIX + mId;
|
||||
}
|
||||
|
||||
public void setLauncher(Launcher launcher) {
|
||||
mLauncher = launcher;
|
||||
mDragController = launcher.getDragController();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDrag(View view, DragEvent event) {
|
||||
if (mLauncher == null || mDragController == null) {
|
||||
postCleanup();
|
||||
return false;
|
||||
}
|
||||
if (event.getAction() == DragEvent.ACTION_DRAG_STARTED) {
|
||||
if (onDragStart(event)) {
|
||||
return true;
|
||||
} else {
|
||||
postCleanup();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return mDragController.onDragEvent(mDragStartTime, event);
|
||||
}
|
||||
|
||||
protected boolean onDragStart(DragEvent event) {
|
||||
ClipDescription desc = event.getClipDescription();
|
||||
if (desc == null || !desc.hasMimeType(getMimeType())) {
|
||||
Log.e(TAG, "Someone started a dragAndDrop before us.");
|
||||
return false;
|
||||
}
|
||||
|
||||
Point downPos = new Point((int) event.getX(), (int) event.getY());
|
||||
DragOptions options = new DragOptions();
|
||||
options.systemDndStartPoint = downPos;
|
||||
options.preDragCondition = this;
|
||||
|
||||
// We use drag event position as the screenPos for the preview image. Since mPreviewRect
|
||||
// already includes the view position relative to the drag event on the source window,
|
||||
// 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.
|
||||
createDragHelper().startDrag(new Rect(mPreviewRect),
|
||||
mPreviewBitmapWidth, mPreviewViewWidth, downPos, this, options);
|
||||
mDragStartTime = SystemClock.uptimeMillis();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected abstract PendingItemDragHelper createDragHelper();
|
||||
|
||||
@Override
|
||||
public boolean shouldStartDrag(double distanceDragged) {
|
||||
// Stay in pre-drag mode, if workspace is locked.
|
||||
return !mLauncher.isWorkspaceLocked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPreDragStart(DropTarget.DragObject dragObject) {
|
||||
// The predrag starts when the workspace is not yet loaded. In some cases we set
|
||||
// the dragLayer alpha to 0 to have a nice fade-in animation. But that will prevent the
|
||||
// dragView from being visible. Instead just skip the fade-in animation here.
|
||||
mLauncher.getDragLayer().setAlpha(1);
|
||||
|
||||
dragObject.dragView.setColor(
|
||||
mLauncher.getResources().getColor(R.color.delete_target_hover_tint));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPreDragEnd(DropTarget.DragObject dragObject, boolean dragStarted) {
|
||||
if (dragStarted) {
|
||||
dragObject.dragView.setColor(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsAppInfoDropTarget() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsDeleteDropTarget() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getIntrinsicIconScaleFactor() {
|
||||
return 1f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDropCompleted(View target, DropTarget.DragObject d, boolean isFlingToDelete,
|
||||
boolean success) {
|
||||
if (isFlingToDelete || !success || (target != mLauncher.getWorkspace() &&
|
||||
!(target instanceof DeleteDropTarget) && !(target instanceof Folder))) {
|
||||
// Exit spring loaded mode if we have not successfully dropped or have not handled the
|
||||
// drop in Workspace
|
||||
mLauncher.exitSpringLoadedDragModeDelayed(true,
|
||||
Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null);
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
d.deferDragViewCleanupPostAnimation = false;
|
||||
}
|
||||
postCleanup();
|
||||
}
|
||||
|
||||
private void postCleanup() {
|
||||
if (mLauncher != null) {
|
||||
// Remove any drag params from the launcher intent since the drag operation is complete.
|
||||
Intent newIntent = new Intent(mLauncher.getIntent());
|
||||
newIntent.removeExtra(EXTRA_PIN_ITEM_DRAG_LISTENER);
|
||||
mLauncher.setIntent(newIntent);
|
||||
}
|
||||
|
||||
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
removeListener();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void removeListener() {
|
||||
if (mLauncher != null) {
|
||||
mLauncher.getDragLayer().setOnDragListener(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,89 +18,49 @@ package com.android.launcher3.dragndrop;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.content.ClipDescription;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.LauncherApps.PinItemRequest;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
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;
|
||||
import com.android.launcher3.DropTarget;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherAppWidgetProviderInfo;
|
||||
import com.android.launcher3.PendingAddItemInfo;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.folder.Folder;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.launcher3.widget.PendingAddShortcutInfo;
|
||||
import com.android.launcher3.widget.PendingAddWidgetInfo;
|
||||
import com.android.launcher3.widget.PendingItemDragHelper;
|
||||
import com.android.launcher3.widget.WidgetAddFlowHandler;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* {@link DragSource} for handling drop from a different window. This object is initialized
|
||||
* in the source window and is passed on to the Launcher activity as an Intent extra.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public class PinItemDragListener
|
||||
implements Parcelable, View.OnDragListener, DragSource, DragOptions.PreDragCondition {
|
||||
public class PinItemDragListener extends BaseItemDragListener implements Parcelable {
|
||||
|
||||
private static final String TAG = "PinItemDragListener";
|
||||
|
||||
private static final String MIME_TYPE_PREFIX = "com.android.launcher3.drag_and_drop/";
|
||||
public static final String EXTRA_PIN_ITEM_DRAG_LISTENER = "pin_item_drag_listener";
|
||||
|
||||
private final PinItemRequest mRequest;
|
||||
|
||||
// Position of preview relative to the touch location
|
||||
private final Rect mPreviewRect;
|
||||
|
||||
private final int mPreviewBitmapWidth;
|
||||
private final int mPreviewViewWidth;
|
||||
|
||||
// Randomly generated id used to verify the drag event.
|
||||
private final String mId;
|
||||
|
||||
private Launcher mLauncher;
|
||||
private DragController mDragController;
|
||||
private long mDragStartTime;
|
||||
|
||||
public PinItemDragListener(PinItemRequest request, Rect previewRect,
|
||||
int previewBitmapWidth, int previewViewWidth) {
|
||||
super(previewRect, previewBitmapWidth, previewViewWidth);
|
||||
mRequest = request;
|
||||
mPreviewRect = previewRect;
|
||||
mPreviewBitmapWidth = previewBitmapWidth;
|
||||
mPreviewViewWidth = previewViewWidth;
|
||||
mId = UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
private PinItemDragListener(Parcel parcel) {
|
||||
super(parcel);
|
||||
mRequest = PinItemRequest.CREATOR.createFromParcel(parcel);
|
||||
mPreviewRect = Rect.CREATOR.createFromParcel(parcel);
|
||||
mPreviewBitmapWidth = parcel.readInt();
|
||||
mPreviewViewWidth = parcel.readInt();
|
||||
mId = parcel.readString();
|
||||
}
|
||||
|
||||
public String getMimeType() {
|
||||
return MIME_TYPE_PREFIX + mId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -110,45 +70,20 @@ public class PinItemDragListener
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel parcel, int i) {
|
||||
super.writeToParcel(parcel, i);
|
||||
mRequest.writeToParcel(parcel, i);
|
||||
mPreviewRect.writeToParcel(parcel, i);
|
||||
parcel.writeInt(mPreviewBitmapWidth);
|
||||
parcel.writeInt(mPreviewViewWidth);
|
||||
parcel.writeString(mId);
|
||||
}
|
||||
|
||||
public void setLauncher(Launcher launcher) {
|
||||
mLauncher = launcher;
|
||||
mDragController = launcher.getDragController();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDrag(View view, DragEvent event) {
|
||||
if (mLauncher == null || mDragController == null) {
|
||||
postCleanup();
|
||||
return false;
|
||||
}
|
||||
if (event.getAction() == DragEvent.ACTION_DRAG_STARTED) {
|
||||
if (onDragStart(event)) {
|
||||
return true;
|
||||
} else {
|
||||
postCleanup();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return mDragController.onDragEvent(mDragStartTime, event);
|
||||
}
|
||||
|
||||
private boolean onDragStart(DragEvent event) {
|
||||
protected boolean onDragStart(DragEvent event) {
|
||||
if (!mRequest.isValid()) {
|
||||
return false;
|
||||
}
|
||||
ClipDescription desc = event.getClipDescription();
|
||||
if (desc == null || !desc.hasMimeType(getMimeType())) {
|
||||
Log.e(TAG, "Someone started a dragAndDrop before us.");
|
||||
return false;
|
||||
}
|
||||
return super.onDragStart(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PendingItemDragHelper createDragHelper() {
|
||||
final PendingAddItemInfo item;
|
||||
if (mRequest.getRequestType() == PinItemRequest.REQUEST_TYPE_SHORTCUT) {
|
||||
item = new PendingAddShortcutInfo(
|
||||
@@ -170,109 +105,17 @@ public class PinItemDragListener
|
||||
View view = new View(mLauncher);
|
||||
view.setTag(item);
|
||||
|
||||
Point downPos = new Point((int) event.getX(), (int) event.getY());
|
||||
DragOptions options = new DragOptions();
|
||||
options.systemDndStartPoint = downPos;
|
||||
options.preDragCondition = this;
|
||||
|
||||
// We use drag event position as the screenPos for the preview image. Since mPreviewRect
|
||||
// already includes the view position relative to the drag event on the source window,
|
||||
// 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.
|
||||
PendingItemDragHelper dragHelper = new PendingItemDragHelper(view);
|
||||
if (mRequest.getRequestType() == PinItemRequest.REQUEST_TYPE_APPWIDGET) {
|
||||
dragHelper.setPreview(getPreview(mRequest));
|
||||
}
|
||||
|
||||
dragHelper.startDrag(new Rect(mPreviewRect),
|
||||
mPreviewBitmapWidth, mPreviewViewWidth, downPos, this, options);
|
||||
mDragStartTime = SystemClock.uptimeMillis();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldStartDrag(double distanceDragged) {
|
||||
// Stay in pre-drag mode, if workspace is locked.
|
||||
return !mLauncher.isWorkspaceLocked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPreDragStart(DropTarget.DragObject dragObject) {
|
||||
// The predrag starts when the workspace is not yet loaded. In some cases we set
|
||||
// the dragLayer alpha to 0 to have a nice fade-in animation. But that will prevent the
|
||||
// dragView from being visible. Instead just skip the fade-in animation here.
|
||||
mLauncher.getDragLayer().setAlpha(1);
|
||||
|
||||
dragObject.dragView.setColor(
|
||||
mLauncher.getResources().getColor(R.color.delete_target_hover_tint));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPreDragEnd(DropTarget.DragObject dragObject, boolean dragStarted) {
|
||||
if (dragStarted) {
|
||||
dragObject.dragView.setColor(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsAppInfoDropTarget() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsDeleteDropTarget() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getIntrinsicIconScaleFactor() {
|
||||
return 1f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDropCompleted(View target, DropTarget.DragObject d, boolean isFlingToDelete,
|
||||
boolean success) {
|
||||
if (isFlingToDelete || !success || (target != mLauncher.getWorkspace() &&
|
||||
!(target instanceof DeleteDropTarget) && !(target instanceof Folder))) {
|
||||
// Exit spring loaded mode if we have not successfully dropped or have not handled the
|
||||
// drop in Workspace
|
||||
mLauncher.exitSpringLoadedDragModeDelayed(true,
|
||||
Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null);
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
d.deferDragViewCleanupPostAnimation = false;
|
||||
}
|
||||
postCleanup();
|
||||
return dragHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillInLogContainerData(View v, ItemInfo info, LauncherLogProto.Target target,
|
||||
LauncherLogProto.Target targetParent) {
|
||||
targetParent.containerType = ContainerType.PINITEM;
|
||||
}
|
||||
|
||||
private void postCleanup() {
|
||||
if (mLauncher != null) {
|
||||
// Remove any drag params from the launcher intent since the drag operation is complete.
|
||||
Intent newIntent = new Intent(mLauncher.getIntent());
|
||||
newIntent.removeExtra(EXTRA_PIN_ITEM_DRAG_LISTENER);
|
||||
mLauncher.setIntent(newIntent);
|
||||
}
|
||||
|
||||
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
removeListener();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void removeListener() {
|
||||
if (mLauncher != null) {
|
||||
mLauncher.getDragLayer().setOnDragListener(null);
|
||||
}
|
||||
targetParent.containerType = LauncherLogProto.ContainerType.PINITEM;
|
||||
}
|
||||
|
||||
public static RemoteViews getPreview(PinItemRequest request) {
|
||||
|
||||
@@ -28,7 +28,6 @@ import android.graphics.RectF;
|
||||
import android.support.v4.graphics.ColorUtils;
|
||||
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.util.Preconditions;
|
||||
|
||||
/**
|
||||
* Utility class to add shadows to bitmaps.
|
||||
@@ -126,7 +125,9 @@ public class ShadowGenerator {
|
||||
}
|
||||
|
||||
public static ShadowGenerator getInstance(Context context) {
|
||||
Preconditions.assertNonUiThread();
|
||||
// TODO: This currently fails as the system default icon also needs a shadow as it
|
||||
// uses adaptive icon.
|
||||
// Preconditions.assertNonUiThread();
|
||||
synchronized (LOCK) {
|
||||
if (sShadowGenerator == null) {
|
||||
sShadowGenerator = new ShadowGenerator(context);
|
||||
|
||||
Reference in New Issue
Block a user