Merge changes I6bf48141,I77b7a2e4 into sc-v2-dev am: f262591ab0
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/14706973 Change-Id: I1a1e76af5f60c72d2a69ae014b0787766425f6cb
This commit is contained in:
@@ -222,7 +222,7 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
|
||||
}
|
||||
|
||||
public boolean isDraggingItem() {
|
||||
return mTaskbarView.isDraggingItem();
|
||||
return mContext.getDragController().isDragging();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,9 +28,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.LauncherApps;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Process;
|
||||
import android.os.SystemProperties;
|
||||
import android.util.Log;
|
||||
@@ -43,22 +41,14 @@ import android.view.WindowManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.DragSource;
|
||||
import com.android.launcher3.DropTarget;
|
||||
import com.android.launcher3.LauncherSettings.Favorites;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.dragndrop.DragController;
|
||||
import com.android.launcher3.dragndrop.DragOptions;
|
||||
import com.android.launcher3.dragndrop.DragView;
|
||||
import com.android.launcher3.dragndrop.DraggableView;
|
||||
import com.android.launcher3.folder.Folder;
|
||||
import com.android.launcher3.folder.FolderIcon;
|
||||
import com.android.launcher3.model.data.FolderInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.taskbar.TaskbarNavButtonController.TaskbarButton;
|
||||
import com.android.launcher3.touch.ItemClickHandler;
|
||||
@@ -89,10 +79,13 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
|
||||
private final LayoutInflater mLayoutInflater;
|
||||
private final TaskbarDragLayer mDragLayer;
|
||||
private final TaskbarIconController mIconController;
|
||||
private final MyDragController mDragController;
|
||||
private final TaskbarDragController mDragController;
|
||||
|
||||
private final WindowManager mWindowManager;
|
||||
private WindowManager.LayoutParams mWindowLayoutParams;
|
||||
private boolean mIsFullscreen;
|
||||
// The size we should return to when we call setTaskbarWindowFullscreen(false)
|
||||
private int mLastRequestedNonFullscreenHeight;
|
||||
|
||||
private final SysUINavigationMode.Mode mNavMode;
|
||||
private final TaskbarNavButtonController mNavButtonController;
|
||||
@@ -114,8 +107,8 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
|
||||
mIsSafeModeEnabled = TraceHelper.allowIpcs("isSafeMode",
|
||||
() -> getPackageManager().isSafeMode());
|
||||
|
||||
mOnTaskbarIconLongClickListener =
|
||||
new TaskbarDragController(this)::startSystemDragOnLongClick;
|
||||
mDragController = new TaskbarDragController(this);
|
||||
mOnTaskbarIconLongClickListener = mDragController::startDragOnLongClick;
|
||||
mOnTaskbarIconClickListener = this::onTaskbarIconClicked;
|
||||
|
||||
float taskbarIconSize = getResources().getDimension(R.dimen.taskbar_icon_size);
|
||||
@@ -126,7 +119,6 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
|
||||
mDragLayer = (TaskbarDragLayer) mLayoutInflater
|
||||
.inflate(R.layout.taskbar, null, false);
|
||||
mIconController = new TaskbarIconController(this, mDragLayer);
|
||||
mDragController = new MyDragController(this);
|
||||
|
||||
Display display = windowContext.getDisplay();
|
||||
Context c = display.getDisplayId() == Display.DEFAULT_DISPLAY
|
||||
@@ -136,9 +128,10 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
|
||||
}
|
||||
|
||||
public void init() {
|
||||
mLastRequestedNonFullscreenHeight = mDeviceProfile.taskbarSize;
|
||||
mWindowLayoutParams = new WindowManager.LayoutParams(
|
||||
MATCH_PARENT,
|
||||
mDeviceProfile.taskbarSize,
|
||||
mLastRequestedNonFullscreenHeight,
|
||||
TYPE_APPLICATION_OVERLAY,
|
||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
|
||||
PixelFormat.TRANSLUCENT);
|
||||
@@ -160,17 +153,6 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
|
||||
mWindowManager.addView(mDragLayer, mWindowLayoutParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the TaskbarContainer height (pass deviceProfile.taskbarSize to reset).
|
||||
*/
|
||||
public void setTaskbarWindowHeight(int height) {
|
||||
if (mWindowLayoutParams.height == height) {
|
||||
return;
|
||||
}
|
||||
mWindowLayoutParams.height = height;
|
||||
mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams);
|
||||
}
|
||||
|
||||
public boolean canShowNavButtons() {
|
||||
return ENABLE_THREE_BUTTON_TASKBAR && mNavMode == Mode.THREE_BUTTONS;
|
||||
}
|
||||
@@ -196,7 +178,7 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
|
||||
}
|
||||
|
||||
@Override
|
||||
public DragController getDragController() {
|
||||
public TaskbarDragController getDragController() {
|
||||
return mDragController;
|
||||
}
|
||||
|
||||
@@ -243,8 +225,30 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
|
||||
/**
|
||||
* Updates the TaskbarContainer to MATCH_PARENT vs original Taskbar size.
|
||||
*/
|
||||
protected void setTaskbarWindowFullscreen(boolean fullscreen) {
|
||||
setTaskbarWindowHeight(fullscreen ? MATCH_PARENT : getDeviceProfile().taskbarSize);
|
||||
public void setTaskbarWindowFullscreen(boolean fullscreen) {
|
||||
mIsFullscreen = fullscreen;
|
||||
setTaskbarWindowHeight(fullscreen ? MATCH_PARENT : mLastRequestedNonFullscreenHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the TaskbarContainer height (pass deviceProfile.taskbarSize to reset).
|
||||
*/
|
||||
public void setTaskbarWindowHeight(int height) {
|
||||
if (mWindowLayoutParams.height == height) {
|
||||
return;
|
||||
}
|
||||
if (height != MATCH_PARENT) {
|
||||
mLastRequestedNonFullscreenHeight = height;
|
||||
if (mIsFullscreen) {
|
||||
// We still need to be fullscreen, so defer any change to our height until we call
|
||||
// setTaskbarWindowFullscreen(false). For example, this could happen when dragging
|
||||
// from the gesture region, as the drag will cancel the gesture and reset launcher's
|
||||
// state, which in turn normally would reset the taskbar window height as well.
|
||||
return;
|
||||
}
|
||||
}
|
||||
mWindowLayoutParams.height = height;
|
||||
mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams);
|
||||
}
|
||||
|
||||
protected void onTaskbarIconClicked(View view) {
|
||||
@@ -307,27 +311,4 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
|
||||
|
||||
AbstractFloatingView.closeAllOpenViews(this);
|
||||
}
|
||||
|
||||
private static class MyDragController extends DragController<TaskbarActivityContext> {
|
||||
MyDragController(TaskbarActivityContext activity) {
|
||||
super(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DragView startDrag(@Nullable Drawable drawable, @Nullable View view,
|
||||
DraggableView originalView, int dragLayerX, int dragLayerY, DragSource source,
|
||||
ItemInfo dragInfo, Point dragOffset, Rect dragRegion, float initialDragViewScale,
|
||||
float dragViewScaleOnDrop, DragOptions options) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void exitDrag() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DropTarget getDefaultDropTarget(int[] dropCoordinates) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,19 +20,35 @@ import static android.view.View.VISIBLE;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipDescription;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.LauncherApps;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.UserHandle;
|
||||
import android.view.DragEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.DragSource;
|
||||
import com.android.launcher3.DropTarget;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.accessibility.DragViewStateAnnouncer;
|
||||
import com.android.launcher3.dragndrop.DragController;
|
||||
import com.android.launcher3.dragndrop.DragDriver;
|
||||
import com.android.launcher3.dragndrop.DragOptions;
|
||||
import com.android.launcher3.dragndrop.DragView;
|
||||
import com.android.launcher3.dragndrop.DraggableView;
|
||||
import com.android.launcher3.graphics.DragPreviewProvider;
|
||||
import com.android.launcher3.icons.FastBitmapDrawable;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
import com.android.systemui.shared.system.ClipDescriptionCompat;
|
||||
@@ -41,14 +57,20 @@ import com.android.systemui.shared.system.LauncherAppsCompat;
|
||||
/**
|
||||
* Handles long click on Taskbar items to start a system drag and drop operation.
|
||||
*/
|
||||
public class TaskbarDragController {
|
||||
public class TaskbarDragController extends DragController<TaskbarActivityContext> {
|
||||
|
||||
private final Context mContext;
|
||||
private final int mDragIconSize;
|
||||
private final int[] mTempXY = new int[2];
|
||||
|
||||
public TaskbarDragController(Context context) {
|
||||
mContext = context;
|
||||
Resources resources = mContext.getResources();
|
||||
// Where the initial touch was relative to the dragged icon.
|
||||
private int mRegistrationX;
|
||||
private int mRegistrationY;
|
||||
|
||||
private boolean mIsSystemDragInProgress;
|
||||
|
||||
public TaskbarDragController(TaskbarActivityContext activity) {
|
||||
super(activity);
|
||||
Resources resources = mActivity.getResources();
|
||||
mDragIconSize = resources.getDimensionPixelSize(R.dimen.taskbar_icon_drag_icon_size);
|
||||
}
|
||||
|
||||
@@ -57,18 +79,146 @@ public class TaskbarDragController {
|
||||
* generate the ClipDescription and Intent.
|
||||
* @return Whether {@link View#startDragAndDrop} started successfully.
|
||||
*/
|
||||
protected boolean startSystemDragOnLongClick(View view) {
|
||||
protected boolean startDragOnLongClick(View view) {
|
||||
if (!(view instanceof BubbleTextView)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BubbleTextView btv = (BubbleTextView) view;
|
||||
View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view) {
|
||||
|
||||
mActivity.setTaskbarWindowFullscreen(true);
|
||||
view.post(() -> {
|
||||
startInternalDrag(btv);
|
||||
btv.setVisibility(INVISIBLE);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
private void startInternalDrag(BubbleTextView btv) {
|
||||
float iconScale = 1f;
|
||||
Drawable icon = btv.getIcon();
|
||||
if (icon instanceof FastBitmapDrawable) {
|
||||
iconScale = ((FastBitmapDrawable) icon).getAnimatedScale();
|
||||
}
|
||||
|
||||
// Clear the pressed state if necessary
|
||||
btv.clearFocus();
|
||||
btv.setPressed(false);
|
||||
btv.clearPressedBackground();
|
||||
|
||||
final DragPreviewProvider previewProvider = new DragPreviewProvider(btv);
|
||||
final Drawable drawable = previewProvider.createDrawable();
|
||||
final float scale = previewProvider.getScaleAndPosition(drawable, mTempXY);
|
||||
int dragLayerX = mTempXY[0];
|
||||
int dragLayerY = mTempXY[1];
|
||||
|
||||
Rect dragRect = new Rect();
|
||||
btv.getSourceVisualDragBounds(dragRect);
|
||||
dragLayerY += dragRect.top;
|
||||
|
||||
DragOptions dragOptions = new DragOptions();
|
||||
// TODO: open popup/pre-drag
|
||||
// PopupContainerWithArrow popupContainer = PopupContainerWithArrow.showForIcon(view);
|
||||
// if (popupContainer != null) {
|
||||
// dragOptions.preDragCondition = popupContainer.createPreDragCondition();
|
||||
// }
|
||||
|
||||
startDrag(
|
||||
drawable,
|
||||
/* view = */ null,
|
||||
/* originalView = */ btv,
|
||||
dragLayerX,
|
||||
dragLayerY,
|
||||
(View target, DropTarget.DragObject d, boolean success) -> {} /* DragSource */,
|
||||
(WorkspaceItemInfo) btv.getTag(),
|
||||
/* dragVisualizeOffset = */ null,
|
||||
dragRect,
|
||||
scale * iconScale,
|
||||
scale,
|
||||
dragOptions);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DragView startDrag(@Nullable Drawable drawable, @Nullable View view,
|
||||
DraggableView originalView, int dragLayerX, int dragLayerY, DragSource source,
|
||||
ItemInfo dragInfo, Point dragOffset, Rect dragRegion, float initialDragViewScale,
|
||||
float dragViewScaleOnDrop, DragOptions options) {
|
||||
mOptions = options;
|
||||
|
||||
mRegistrationX = mMotionDown.x - dragLayerX;
|
||||
mRegistrationY = mMotionDown.y - dragLayerY;
|
||||
|
||||
final int dragRegionLeft = dragRegion == null ? 0 : dragRegion.left;
|
||||
final int dragRegionTop = dragRegion == null ? 0 : dragRegion.top;
|
||||
|
||||
mLastDropTarget = null;
|
||||
|
||||
mDragObject = new DropTarget.DragObject(mActivity.getApplicationContext());
|
||||
mDragObject.originalView = originalView;
|
||||
|
||||
mIsInPreDrag = mOptions.preDragCondition != null
|
||||
&& !mOptions.preDragCondition.shouldStartDrag(0);
|
||||
|
||||
float scalePx = mDragIconSize - dragRegion.width();
|
||||
final DragView dragView = mDragObject.dragView = new TaskbarDragView(
|
||||
mActivity,
|
||||
drawable,
|
||||
mRegistrationX,
|
||||
mRegistrationY,
|
||||
initialDragViewScale,
|
||||
dragViewScaleOnDrop,
|
||||
scalePx);
|
||||
dragView.setItemInfo(dragInfo);
|
||||
mDragObject.dragComplete = false;
|
||||
|
||||
mDragObject.xOffset = mMotionDown.x - (dragLayerX + dragRegionLeft);
|
||||
mDragObject.yOffset = mMotionDown.y - (dragLayerY + dragRegionTop);
|
||||
|
||||
mDragDriver = DragDriver.create(this, mOptions, /* secondaryEventConsumer = */ ev -> {});
|
||||
if (!mOptions.isAccessibleDrag) {
|
||||
mDragObject.stateAnnouncer = DragViewStateAnnouncer.createFor(dragView);
|
||||
}
|
||||
|
||||
mDragObject.dragSource = source;
|
||||
mDragObject.dragInfo = dragInfo;
|
||||
mDragObject.originalDragInfo = mDragObject.dragInfo.makeShallowCopy();
|
||||
|
||||
if (dragRegion != null) {
|
||||
dragView.setDragRegion(new Rect(dragRegion));
|
||||
}
|
||||
|
||||
dragView.show(mLastTouch.x, mLastTouch.y);
|
||||
mDistanceSinceScroll = 0;
|
||||
|
||||
if (!mIsInPreDrag) {
|
||||
callOnDragStart();
|
||||
} else if (mOptions.preDragCondition != null) {
|
||||
mOptions.preDragCondition.onPreDragStart(mDragObject);
|
||||
}
|
||||
|
||||
handleMoveEvent(mLastTouch.x, mLastTouch.y);
|
||||
|
||||
return dragView;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void callOnDragStart() {
|
||||
super.callOnDragStart();
|
||||
// Pre-drag has ended, start the global system drag.
|
||||
AbstractFloatingView.closeAllOpenViews(mActivity);
|
||||
startSystemDrag((BubbleTextView) mDragObject.originalView);
|
||||
}
|
||||
|
||||
private void startSystemDrag(BubbleTextView btv) {
|
||||
View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(btv) {
|
||||
|
||||
@Override
|
||||
public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
|
||||
shadowSize.set(mDragIconSize, mDragIconSize);
|
||||
// TODO: should be based on last touch point on the icon.
|
||||
shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
|
||||
// The registration point was taken before the icon scaled to mDragIconSize, so
|
||||
// offset the registration to where the touch is on the new size.
|
||||
int offset = (mDragIconSize - btv.getIconSize()) / 2;
|
||||
shadowTouchPoint.set(mRegistrationX + offset, mRegistrationY + offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -81,12 +231,12 @@ public class TaskbarDragController {
|
||||
}
|
||||
};
|
||||
|
||||
Object tag = view.getTag();
|
||||
Object tag = btv.getTag();
|
||||
ClipDescription clipDescription = null;
|
||||
Intent intent = null;
|
||||
if (tag instanceof WorkspaceItemInfo) {
|
||||
WorkspaceItemInfo item = (WorkspaceItemInfo) tag;
|
||||
LauncherApps launcherApps = mContext.getSystemService(LauncherApps.class);
|
||||
LauncherApps launcherApps = mActivity.getSystemService(LauncherApps.class);
|
||||
clipDescription = new ClipDescription(item.title,
|
||||
new String[] {
|
||||
item.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT
|
||||
@@ -116,28 +266,89 @@ public class TaskbarDragController {
|
||||
|
||||
if (clipDescription != null && intent != null) {
|
||||
ClipData clipData = new ClipData(clipDescription, new ClipData.Item(intent));
|
||||
view.setOnDragListener(getDraggedViewDragListener());
|
||||
return view.startDragAndDrop(clipData, shadowBuilder, null /* localState */,
|
||||
View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_OPAQUE);
|
||||
if (btv.startDragAndDrop(clipData, shadowBuilder, null /* localState */,
|
||||
View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_OPAQUE)) {
|
||||
onSystemDragStarted();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide the original Taskbar item while it is being dragged.
|
||||
*/
|
||||
private View.OnDragListener getDraggedViewDragListener() {
|
||||
return (view, dragEvent) -> {
|
||||
private void onSystemDragStarted() {
|
||||
mIsSystemDragInProgress = true;
|
||||
mActivity.getDragLayer().setOnDragListener((view, dragEvent) -> {
|
||||
switch (dragEvent.getAction()) {
|
||||
case DragEvent.ACTION_DRAG_STARTED:
|
||||
view.setVisibility(INVISIBLE);
|
||||
// Return true to tell system we are interested in events, so we get DRAG_ENDED.
|
||||
return true;
|
||||
case DragEvent.ACTION_DRAG_ENDED:
|
||||
view.setVisibility(VISIBLE);
|
||||
view.setOnDragListener(null);
|
||||
mIsSystemDragInProgress = false;
|
||||
maybeOnDragEnd();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDragging() {
|
||||
return super.isDragging() || mIsSystemDragInProgress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether we started dragging the given view and the drag is still in progress.
|
||||
*/
|
||||
public boolean isDraggingView(View child) {
|
||||
return isDragging() && mDragObject != null && mDragObject.originalView == child;
|
||||
}
|
||||
|
||||
private void maybeOnDragEnd() {
|
||||
if (!isDragging()) {
|
||||
((View) mDragObject.originalView).setVisibility(VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void callOnDragEnd() {
|
||||
super.callOnDragEnd();
|
||||
maybeOnDragEnd();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getX(MotionEvent ev) {
|
||||
// We will resize to fill the screen while dragging, so use screen coordinates. This ensures
|
||||
// we start at the correct position even though touch down is on the smaller DragLayer size.
|
||||
return ev.getRawX();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getY(MotionEvent ev) {
|
||||
// We will resize to fill the screen while dragging, so use screen coordinates. This ensures
|
||||
// we start at the correct position even though touch down is on the smaller DragLayer size.
|
||||
return ev.getRawY();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Point getClampedDragLayerPos(float x, float y) {
|
||||
// No need to clamp, as we will take up the entire screen.
|
||||
mTmpPoint.set(Math.round(x), Math.round(y));
|
||||
return mTmpPoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void exitDrag() {
|
||||
if (mDragObject != null) {
|
||||
mActivity.getDragLayer().removeView(mDragObject.dragView);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDropTarget(DropTarget target) {
|
||||
// No-op as Taskbar currently doesn't support any drop targets internally.
|
||||
// Note: if we do add internal DropTargets, we'll still need to ignore Folder.
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DropTarget getDefaultDropTarget(int[] dropCoordinates) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ public class TaskbarDragLayer extends BaseDragLayer<TaskbarActivityContext> {
|
||||
private final int mFolderMargin;
|
||||
private final Paint mTaskbarBackgroundPaint;
|
||||
|
||||
private TaskbarIconController.Callbacks mControllerCallbacks;
|
||||
private TaskbarIconController.TaskbarDragLayerCallbacks mControllerCallbacks;
|
||||
private TaskbarView mTaskbarView;
|
||||
|
||||
private final OnComputeInsetsListener mTaskbarInsetsComputer = this::onComputeTaskbarInsets;
|
||||
@@ -69,10 +69,11 @@ public class TaskbarDragLayer extends BaseDragLayer<TaskbarActivityContext> {
|
||||
|
||||
@Override
|
||||
public void recreateControllers() {
|
||||
mControllers = new TouchController[0];
|
||||
mControllers = new TouchController[] {mActivity.getDragController()};
|
||||
}
|
||||
|
||||
public void init(TaskbarIconController.Callbacks callbacks, TaskbarView taskbarView) {
|
||||
public void init(TaskbarIconController.TaskbarDragLayerCallbacks callbacks,
|
||||
TaskbarView taskbarView) {
|
||||
mControllerCallbacks = callbacks;
|
||||
mTaskbarView = taskbarView;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.taskbar;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.dragndrop.DragView;
|
||||
|
||||
/**
|
||||
* A DragView drawn/used by the Taskbar. Note that this is only for the internal drag-and-drop,
|
||||
* while the pre-drag is still in progress (i.e. when the long press popup is still open). After
|
||||
* that ends, we switch to a system drag and drop view instead.
|
||||
*/
|
||||
public class TaskbarDragView extends DragView<TaskbarActivityContext> {
|
||||
public TaskbarDragView(TaskbarActivityContext launcher, Drawable drawable, int registrationX,
|
||||
int registrationY, float initialScale, float scaleOnDrop, float finalScaleDps) {
|
||||
super(launcher, drawable, registrationX, registrationY, initialScale, scaleOnDrop,
|
||||
finalScaleDps);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void animateTo(int toTouchX, int toTouchY, Runnable onCompleteRunnable, int duration) {
|
||||
Runnable onAnimationEnd = () -> {
|
||||
if (onCompleteRunnable != null) {
|
||||
onCompleteRunnable.run();
|
||||
}
|
||||
mActivity.getDragLayer().removeView(this);
|
||||
};
|
||||
|
||||
duration = Math.max(duration,
|
||||
getResources().getInteger(R.integer.config_dropAnimMinDuration));
|
||||
|
||||
animate()
|
||||
.translationX(toTouchX - mRegistrationX)
|
||||
.translationY(toTouchY - mRegistrationY)
|
||||
.scaleX(mScaleOnDrop)
|
||||
.scaleY(mScaleOnDrop)
|
||||
.withEndAction(onAnimationEnd)
|
||||
.setDuration(duration)
|
||||
.start();
|
||||
}
|
||||
}
|
||||
@@ -62,10 +62,11 @@ public class TaskbarIconController {
|
||||
|
||||
ButtonProvider buttonProvider = new ButtonProvider(mActivity);
|
||||
mImeBarView.init(buttonProvider);
|
||||
mTaskbarView.construct(clickListener, longClickListener, buttonProvider);
|
||||
mTaskbarView.init(new TaskbarViewCallbacks(), clickListener, longClickListener,
|
||||
buttonProvider);
|
||||
mTaskbarView.getLayoutParams().height = mActivity.getDeviceProfile().taskbarSize;
|
||||
|
||||
mDragLayer.init(new Callbacks(), mTaskbarView);
|
||||
mDragLayer.init(new TaskbarDragLayerCallbacks(), mTaskbarView);
|
||||
}
|
||||
|
||||
public void onDestroy() {
|
||||
@@ -102,7 +103,7 @@ public class TaskbarIconController {
|
||||
/**
|
||||
* Callbacks for {@link TaskbarDragLayer} to interact with the icon controller
|
||||
*/
|
||||
public class Callbacks {
|
||||
public class TaskbarDragLayerCallbacks {
|
||||
|
||||
/**
|
||||
* Called to update the touchable insets
|
||||
@@ -160,4 +161,16 @@ public class TaskbarIconController {
|
||||
mImeBarView.setVisibility(alpha == 0 ? GONE : VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callbacks for {@link TaskbarView} to interact with the icon controller
|
||||
*/
|
||||
public class TaskbarViewCallbacks {
|
||||
/**
|
||||
* Returns whether no other controller is currently handling the given View's visibility.
|
||||
*/
|
||||
public boolean canUpdateViewVisibility(View child) {
|
||||
return !mActivity.getDragController().isDraggingView(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.DragEvent;
|
||||
import android.view.Gravity;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
@@ -35,7 +34,6 @@ import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.Insettable;
|
||||
import com.android.launcher3.R;
|
||||
@@ -62,7 +60,8 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa
|
||||
|
||||
private final TaskbarActivityContext mActivityContext;
|
||||
|
||||
// Initialized in TaskbarController constructor.
|
||||
// Initialized in init.
|
||||
private TaskbarIconController.TaskbarViewCallbacks mControllerCallbacks;
|
||||
private View.OnClickListener mIconClickListener;
|
||||
private View.OnLongClickListener mIconLongClickListener;
|
||||
|
||||
@@ -75,7 +74,6 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa
|
||||
// Prevents dispatching touches to children if true
|
||||
private boolean mTouchEnabled = true;
|
||||
|
||||
private boolean mIsDraggingItem;
|
||||
// Only non-null when the corresponding Folder is open.
|
||||
private @Nullable FolderIcon mLeaveBehindFolderIcon;
|
||||
|
||||
@@ -118,8 +116,10 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa
|
||||
mHotseatIconsContainer = findViewById(R.id.hotseat_icons_layout);
|
||||
}
|
||||
|
||||
protected void construct(OnClickListener clickListener, OnLongClickListener longClickListener,
|
||||
ButtonProvider buttonProvider) {
|
||||
protected void init(TaskbarIconController.TaskbarViewCallbacks callbacks,
|
||||
OnClickListener clickListener, OnLongClickListener longClickListener,
|
||||
ButtonProvider buttonProvider) {
|
||||
mControllerCallbacks = callbacks;
|
||||
mIconClickListener = clickListener;
|
||||
mIconLongClickListener = longClickListener;
|
||||
mButtonProvider = buttonProvider;
|
||||
@@ -225,6 +225,9 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa
|
||||
}
|
||||
|
||||
private void updateHotseatItemVisibility(View hotseatView) {
|
||||
if (!mControllerCallbacks.canUpdateViewVisibility(hotseatView)) {
|
||||
return;
|
||||
}
|
||||
hotseatView.setVisibility(
|
||||
hotseatView.getTag() != null ? VISIBLE : (mAreHolesAllowed ? INVISIBLE : GONE));
|
||||
}
|
||||
@@ -349,24 +352,6 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa
|
||||
mSystemButtonContainer.addView(mButtonProvider.getRecents(), buttonParams);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDragEvent(DragEvent event) {
|
||||
switch (event.getAction()) {
|
||||
case DragEvent.ACTION_DRAG_STARTED:
|
||||
mIsDraggingItem = true;
|
||||
AbstractFloatingView.closeAllOpenViews(mActivityContext);
|
||||
return true;
|
||||
case DragEvent.ACTION_DRAG_ENDED:
|
||||
mIsDraggingItem = false;
|
||||
break;
|
||||
}
|
||||
return super.onDragEvent(event);
|
||||
}
|
||||
|
||||
public boolean isDraggingItem() {
|
||||
return mIsDraggingItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The bounding box of where the hotseat elements are relative to this TaskbarView.
|
||||
*/
|
||||
|
||||
@@ -403,7 +403,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
}
|
||||
}
|
||||
|
||||
void clearPressedBackground() {
|
||||
public void clearPressedBackground() {
|
||||
setPressed(false);
|
||||
setStayPressed(false);
|
||||
}
|
||||
@@ -849,8 +849,9 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
switch (display) {
|
||||
case DISPLAY_ALL_APPS:
|
||||
return grid.allAppsIconSizePx;
|
||||
case DISPLAY_WORKSPACE:
|
||||
case DISPLAY_FOLDER:
|
||||
return grid.folderChildIconSizePx;
|
||||
case DISPLAY_WORKSPACE:
|
||||
default:
|
||||
return grid.iconSizePx;
|
||||
}
|
||||
|
||||
@@ -1289,7 +1289,8 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
|
||||
}
|
||||
}
|
||||
|
||||
public FolderIcon findFolderIcon(final int folderIconId) {
|
||||
@Override
|
||||
public @Nullable FolderIcon findFolderIcon(final int folderIconId) {
|
||||
return (FolderIcon) mWorkspace.getHomescreenIconByItemId(folderIconId);
|
||||
}
|
||||
|
||||
|
||||
@@ -85,6 +85,7 @@ import com.android.launcher3.shortcuts.ShortcutKey;
|
||||
import com.android.launcher3.shortcuts.ShortcutRequest;
|
||||
import com.android.launcher3.util.IntArray;
|
||||
import com.android.launcher3.util.PackageManagerHelper;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
import com.android.launcher3.views.BaseDragLayer;
|
||||
import com.android.launcher3.widget.PendingAddShortcutInfo;
|
||||
|
||||
@@ -651,25 +652,26 @@ public final class Utilities {
|
||||
* @param outObj this is set to the internal data associated with {@param info},
|
||||
* eg {@link LauncherActivityInfo} or {@link ShortcutInfo}.
|
||||
*/
|
||||
public static Drawable getFullDrawable(Launcher launcher, ItemInfo info, int width, int height,
|
||||
public static Drawable getFullDrawable(Context context, ItemInfo info, int width, int height,
|
||||
Object[] outObj) {
|
||||
Drawable icon = loadFullDrawableWithoutTheme(launcher, info, width, height, outObj);
|
||||
Drawable icon = loadFullDrawableWithoutTheme(context, info, width, height, outObj);
|
||||
if (icon instanceof BitmapInfo.Extender) {
|
||||
icon = ((BitmapInfo.Extender) icon).getThemedDrawable(launcher);
|
||||
icon = ((BitmapInfo.Extender) icon).getThemedDrawable(context);
|
||||
}
|
||||
return icon;
|
||||
}
|
||||
|
||||
private static Drawable loadFullDrawableWithoutTheme(Launcher launcher, ItemInfo info,
|
||||
private static Drawable loadFullDrawableWithoutTheme(Context context, ItemInfo info,
|
||||
int width, int height, Object[] outObj) {
|
||||
LauncherAppState appState = LauncherAppState.getInstance(launcher);
|
||||
ActivityContext activity = ActivityContext.lookupContext(context);
|
||||
LauncherAppState appState = LauncherAppState.getInstance(context);
|
||||
if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
|
||||
LauncherActivityInfo activityInfo = launcher.getSystemService(LauncherApps.class)
|
||||
LauncherActivityInfo activityInfo = context.getSystemService(LauncherApps.class)
|
||||
.resolveActivity(info.getIntent(), info.user);
|
||||
outObj[0] = activityInfo;
|
||||
return activityInfo == null ? null : LauncherAppState.getInstance(launcher)
|
||||
return activityInfo == null ? null : LauncherAppState.getInstance(context)
|
||||
.getIconProvider().getIcon(
|
||||
activityInfo, launcher.getDeviceProfile().inv.fillResIconDpi);
|
||||
activityInfo, activity.getDeviceProfile().inv.fillResIconDpi);
|
||||
} else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
|
||||
if (info instanceof PendingAddShortcutInfo) {
|
||||
ShortcutConfigActivityInfo activityInfo =
|
||||
@@ -678,18 +680,18 @@ public final class Utilities {
|
||||
return activityInfo.getFullResIcon(appState.getIconCache());
|
||||
}
|
||||
List<ShortcutInfo> si = ShortcutKey.fromItemInfo(info)
|
||||
.buildRequest(launcher)
|
||||
.buildRequest(context)
|
||||
.query(ShortcutRequest.ALL);
|
||||
if (si.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
outObj[0] = si.get(0);
|
||||
return ShortcutCachingLogic.getIcon(launcher, si.get(0),
|
||||
return ShortcutCachingLogic.getIcon(context, si.get(0),
|
||||
appState.getInvariantDeviceProfile().fillResIconDpi);
|
||||
}
|
||||
} else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
|
||||
FolderAdaptiveIcon icon = FolderAdaptiveIcon.createFolderAdaptiveIcon(
|
||||
launcher, info.id, new Point(width, height));
|
||||
activity, info.id, new Point(width, height));
|
||||
if (icon == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -707,8 +709,8 @@ public final class Utilities {
|
||||
* badge. When dragged from workspace or folder, it may contain app AND/OR work profile badge
|
||||
**/
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public static Drawable getBadge(Launcher launcher, ItemInfo info, Object obj) {
|
||||
LauncherAppState appState = LauncherAppState.getInstance(launcher);
|
||||
public static Drawable getBadge(Context context, ItemInfo info, Object obj) {
|
||||
LauncherAppState appState = LauncherAppState.getInstance(context);
|
||||
int iconSize = appState.getInvariantDeviceProfile().iconBitmapSize;
|
||||
if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
|
||||
boolean iconBadged = (info instanceof ItemInfoWithIcon)
|
||||
@@ -728,7 +730,7 @@ public final class Utilities {
|
||||
} else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
|
||||
return ((FolderAdaptiveIcon) obj).getBadge();
|
||||
} else {
|
||||
return launcher.getPackageManager()
|
||||
return context.getPackageManager()
|
||||
.getUserBadgedIcon(new FixedSizeEmptyDrawable(iconSize), info.user);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ public abstract class DragController<T extends ActivityContext>
|
||||
/** Coordinate for last touch event **/
|
||||
protected final Point mLastTouch = new Point();
|
||||
|
||||
private final Point mTmpPoint = new Point();
|
||||
protected final Point mTmpPoint = new Point();
|
||||
|
||||
protected DropTarget.DragObject mDragObject;
|
||||
|
||||
@@ -317,7 +317,7 @@ public abstract class DragController<T extends ActivityContext>
|
||||
mDragObject.dragView.animateTo(mMotionDown.x, mMotionDown.y, onCompleteRunnable, duration);
|
||||
}
|
||||
|
||||
private void callOnDragEnd() {
|
||||
protected void callOnDragEnd() {
|
||||
if (mIsInPreDrag && mOptions.preDragCondition != null) {
|
||||
mOptions.preDragCondition.onPreDragEnd(mDragObject, false /* dragStarted*/);
|
||||
}
|
||||
@@ -343,7 +343,7 @@ public abstract class DragController<T extends ActivityContext>
|
||||
/**
|
||||
* Clamps the position to the drag layer bounds.
|
||||
*/
|
||||
private Point getClampedDragLayerPos(float x, float y) {
|
||||
protected Point getClampedDragLayerPos(float x, float y) {
|
||||
mActivity.getDragLayer().getLocalVisibleRect(mRectTemp);
|
||||
mTmpPoint.x = (int) Math.max(mRectTemp.left, Math.min(x, mRectTemp.right - 1));
|
||||
mTmpPoint.y = (int) Math.max(mRectTemp.top, Math.min(y, mRectTemp.bottom - 1));
|
||||
@@ -390,7 +390,7 @@ public abstract class DragController<T extends ActivityContext>
|
||||
return false;
|
||||
}
|
||||
|
||||
Point dragLayerPos = getClampedDragLayerPos(ev.getX(), ev.getY());
|
||||
Point dragLayerPos = getClampedDragLayerPos(getX(ev), getY(ev));
|
||||
mLastTouch.set(dragLayerPos.x, dragLayerPos.y);
|
||||
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
// Remember location of down touch
|
||||
@@ -403,6 +403,14 @@ public abstract class DragController<T extends ActivityContext>
|
||||
return mDragDriver != null && mDragDriver.onInterceptTouchEvent(ev);
|
||||
}
|
||||
|
||||
protected float getX(MotionEvent ev) {
|
||||
return ev.getX();
|
||||
}
|
||||
|
||||
protected float getY(MotionEvent ev) {
|
||||
return ev.getY();
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this from a drag source view.
|
||||
*/
|
||||
|
||||
@@ -165,8 +165,11 @@ public abstract class DragDriver {
|
||||
* Class for driving an internal (i.e. not using framework) drag/drop operation.
|
||||
*/
|
||||
static class InternalDragDriver extends DragDriver {
|
||||
private final DragController mDragController;
|
||||
|
||||
InternalDragDriver(DragController dragController, Consumer<MotionEvent> sec) {
|
||||
super(dragController, sec);
|
||||
mDragController = dragController;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -176,11 +179,14 @@ public abstract class DragDriver {
|
||||
|
||||
switch (action) {
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
mEventListener.onDriverDragMove(ev.getX(), ev.getY());
|
||||
mEventListener.onDriverDragMove(mDragController.getX(ev),
|
||||
mDragController.getY(ev));
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
mEventListener.onDriverDragMove(ev.getX(), ev.getY());
|
||||
mEventListener.onDriverDragEnd(ev.getX(), ev.getY());
|
||||
mEventListener.onDriverDragMove(mDragController.getX(ev),
|
||||
mDragController.getY(ev));
|
||||
mEventListener.onDriverDragEnd(mDragController.getX(ev),
|
||||
mDragController.getY(ev));
|
||||
break;
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
mEventListener.onDriverDragCancel();
|
||||
@@ -197,7 +203,8 @@ public abstract class DragDriver {
|
||||
|
||||
switch (action) {
|
||||
case MotionEvent.ACTION_UP:
|
||||
mEventListener.onDriverDragEnd(ev.getX(), ev.getY());
|
||||
mEventListener.onDriverDragEnd(mDragController.getX(ev),
|
||||
mDragController.getY(ev));
|
||||
break;
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
mEventListener.onDriverDragCancel();
|
||||
|
||||
@@ -53,22 +53,19 @@ import androidx.dynamicanimation.animation.FloatPropertyCompat;
|
||||
import androidx.dynamicanimation.animation.SpringAnimation;
|
||||
import androidx.dynamicanimation.animation.SpringForce;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.icons.FastBitmapDrawable;
|
||||
import com.android.launcher3.icons.LauncherIcons;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.statemanager.StateManager.StateListener;
|
||||
import com.android.launcher3.util.RunnableList;
|
||||
import com.android.launcher3.util.Thunk;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
import com.android.launcher3.views.BaseDragLayer;
|
||||
|
||||
/** A custom view for rendering an icon, folder, shortcut or widget during drag-n-drop. */
|
||||
public class DragView extends FrameLayout implements StateListener<LauncherState> {
|
||||
public abstract class DragView<T extends Context & ActivityContext> extends FrameLayout {
|
||||
|
||||
public static final int VIEW_ZOOM_DURATION = 150;
|
||||
|
||||
@@ -81,19 +78,18 @@ public class DragView extends FrameLayout implements StateListener<LauncherState
|
||||
private final int mHeight;
|
||||
|
||||
private final int mBlurSizeOutline;
|
||||
private final int mRegistrationX;
|
||||
private final int mRegistrationY;
|
||||
protected final int mRegistrationX;
|
||||
protected final int mRegistrationY;
|
||||
private final float mInitialScale;
|
||||
private final float mScaleOnDrop;
|
||||
private final int[] mTempLoc = new int[2];
|
||||
protected final float mScaleOnDrop;
|
||||
protected final int[] mTempLoc = new int[2];
|
||||
|
||||
private final RunnableList mOnDragStartCallback = new RunnableList();
|
||||
|
||||
private Point mDragVisualizeOffset = null;
|
||||
private Rect mDragRegion = null;
|
||||
private final Launcher mLauncher;
|
||||
private final DragLayer mDragLayer;
|
||||
@Thunk final DragController mDragController;
|
||||
protected final T mActivity;
|
||||
private final BaseDragLayer<T> mDragLayer;
|
||||
private boolean mHasDrawn = false;
|
||||
|
||||
final ValueAnimator mAnim;
|
||||
@@ -109,7 +105,7 @@ public class DragView extends FrameLayout implements StateListener<LauncherState
|
||||
private Path mScaledMaskPath;
|
||||
private Drawable mBadge;
|
||||
|
||||
public DragView(Launcher launcher, Drawable drawable, int registrationX,
|
||||
public DragView(T launcher, Drawable drawable, int registrationX,
|
||||
int registrationY, final float initialScale, final float scaleOnDrop,
|
||||
final float finalScaleDps) {
|
||||
this(launcher, getViewFromDrawable(launcher, drawable),
|
||||
@@ -122,7 +118,7 @@ public class DragView extends FrameLayout implements StateListener<LauncherState
|
||||
* <p>
|
||||
* The registration point is the point inside our view that the touch events should
|
||||
* be centered upon.
|
||||
* @param launcher The Launcher instance
|
||||
* @param activity The Launcher instance/ActivityContext this DragView is in.
|
||||
* @param content the view content that is attached to the drag view.
|
||||
* @param width the width of the dragView
|
||||
* @param height the height of the dragView
|
||||
@@ -132,13 +128,12 @@ public class DragView extends FrameLayout implements StateListener<LauncherState
|
||||
* @param scaleOnDrop the scale used in the drop animation.
|
||||
* @param finalScaleDps the scale used in the zoom out animation when the drag view is shown.
|
||||
*/
|
||||
public DragView(Launcher launcher, View content, int width, int height, int registrationX,
|
||||
public DragView(T activity, View content, int width, int height, int registrationX,
|
||||
int registrationY, final float initialScale, final float scaleOnDrop,
|
||||
final float finalScaleDps) {
|
||||
super(launcher);
|
||||
mLauncher = launcher;
|
||||
mDragLayer = launcher.getDragLayer();
|
||||
mDragController = launcher.getDragController();
|
||||
super(activity);
|
||||
mActivity = activity;
|
||||
mDragLayer = activity.getDragLayer();
|
||||
|
||||
mContent = content;
|
||||
mWidth = width;
|
||||
@@ -187,24 +182,6 @@ public class DragView extends FrameLayout implements StateListener<LauncherState
|
||||
setWillNotDraw(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
mLauncher.getStateManager().addStateListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
mLauncher.getStateManager().removeStateListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStateTransitionComplete(LauncherState finalState) {
|
||||
setVisibility((finalState == LauncherState.NORMAL
|
||||
|| finalState == LauncherState.SPRING_LOADED) ? VISIBLE : INVISIBLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize {@code #mIconDrawable} if the item can be represented using
|
||||
* an {@link AdaptiveIconDrawable} or {@link FolderAdaptiveIcon}.
|
||||
@@ -221,10 +198,10 @@ public class DragView extends FrameLayout implements StateListener<LauncherState
|
||||
Object[] outObj = new Object[1];
|
||||
int w = mWidth;
|
||||
int h = mHeight;
|
||||
Drawable dr = Utilities.getFullDrawable(mLauncher, info, w, h, outObj);
|
||||
Drawable dr = Utilities.getFullDrawable(mActivity, info, w, h, outObj);
|
||||
|
||||
if (dr instanceof AdaptiveIconDrawable) {
|
||||
int blurMargin = (int) mLauncher.getResources()
|
||||
int blurMargin = (int) mActivity.getResources()
|
||||
.getDimension(R.dimen.blur_size_medium_outline) / 2;
|
||||
|
||||
Rect bounds = new Rect(0, 0, w, h);
|
||||
@@ -232,13 +209,13 @@ public class DragView extends FrameLayout implements StateListener<LauncherState
|
||||
// Badge is applied after icon normalization so the bounds for badge should not
|
||||
// be scaled down due to icon normalization.
|
||||
Rect badgeBounds = new Rect(bounds);
|
||||
mBadge = getBadge(mLauncher, info, outObj[0]);
|
||||
mBadge = getBadge(mActivity, info, outObj[0]);
|
||||
mBadge.setBounds(badgeBounds);
|
||||
|
||||
// Do not draw the background in case of folder as its translucent
|
||||
final boolean shouldDrawBackground = !(dr instanceof FolderAdaptiveIcon);
|
||||
|
||||
try (LauncherIcons li = LauncherIcons.obtain(mLauncher)) {
|
||||
try (LauncherIcons li = LauncherIcons.obtain(mActivity)) {
|
||||
Drawable nDr; // drawable to be normalized
|
||||
if (shouldDrawBackground) {
|
||||
nDr = dr;
|
||||
@@ -429,12 +406,11 @@ public class DragView extends FrameLayout implements StateListener<LauncherState
|
||||
applyTranslation();
|
||||
}
|
||||
|
||||
public void animateTo(int toTouchX, int toTouchY, Runnable onCompleteRunnable, int duration) {
|
||||
mTempLoc[0] = toTouchX - mRegistrationX;
|
||||
mTempLoc[1] = toTouchY - mRegistrationY;
|
||||
mDragLayer.animateViewIntoPosition(this, mTempLoc, 1f, mScaleOnDrop, mScaleOnDrop,
|
||||
DragLayer.ANIMATION_END_DISAPPEAR, onCompleteRunnable, duration);
|
||||
}
|
||||
/**
|
||||
* Animate this DragView to the given DragLayer coordinates and then remove it.
|
||||
*/
|
||||
public abstract void animateTo(int toTouchX, int toTouchY, Runnable onCompleteRunnable,
|
||||
int duration);
|
||||
|
||||
public void animateShift(final int shiftX, final int shiftY) {
|
||||
if (mAnim.isStarted()) {
|
||||
@@ -470,7 +446,7 @@ public class DragView extends FrameLayout implements StateListener<LauncherState
|
||||
Picture picture = new Picture();
|
||||
mContent.draw(picture.beginRecording(mWidth, mHeight));
|
||||
picture.endRecording();
|
||||
View view = new View(mLauncher);
|
||||
View view = new View(mActivity);
|
||||
view.setClipToOutline(mContent.getClipToOutline());
|
||||
view.setOutlineProvider(mContent.getOutlineProvider());
|
||||
view.setBackground(new PictureDrawable(picture));
|
||||
|
||||
@@ -32,12 +32,12 @@ import android.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.folder.FolderIcon;
|
||||
import com.android.launcher3.folder.PreviewBackground;
|
||||
import com.android.launcher3.graphics.ShiftedBitmapDrawable;
|
||||
import com.android.launcher3.icons.BitmapRenderer;
|
||||
import com.android.launcher3.util.Preconditions;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
|
||||
/**
|
||||
* {@link AdaptiveIconDrawable} representation of a {@link FolderIcon}
|
||||
@@ -70,14 +70,14 @@ public class FolderAdaptiveIcon extends AdaptiveIconDrawable {
|
||||
}
|
||||
|
||||
public static @Nullable FolderAdaptiveIcon createFolderAdaptiveIcon(
|
||||
Launcher launcher, int folderId, Point dragViewSize) {
|
||||
ActivityContext activity, int folderId, Point dragViewSize) {
|
||||
Preconditions.assertNonUiThread();
|
||||
|
||||
// Create the actual drawable on the UI thread to avoid race conditions with
|
||||
// FolderIcon draw pass
|
||||
try {
|
||||
return MAIN_EXECUTOR.submit(() -> {
|
||||
FolderIcon icon = launcher.findFolderIcon(folderId);
|
||||
FolderIcon icon = activity.findFolderIcon(folderId);
|
||||
return icon == null ? null : createDrawableOnUiThread(icon, dragViewSize);
|
||||
|
||||
}).get();
|
||||
|
||||
@@ -96,7 +96,7 @@ public class LauncherDragController extends DragController<Launcher> {
|
||||
final float scaleDps = mIsInPreDrag
|
||||
? res.getDimensionPixelSize(R.dimen.pre_drag_view_scale) : 0f;
|
||||
final DragView dragView = mDragObject.dragView = drawable != null
|
||||
? new DragView(
|
||||
? new LauncherDragView(
|
||||
mActivity,
|
||||
drawable,
|
||||
registrationX,
|
||||
@@ -104,7 +104,7 @@ public class LauncherDragController extends DragController<Launcher> {
|
||||
initialDragViewScale,
|
||||
dragViewScaleOnDrop,
|
||||
scaleDps)
|
||||
: new DragView(
|
||||
: new LauncherDragView(
|
||||
mActivity,
|
||||
view,
|
||||
view.getMeasuredWidth(),
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.graphics.drawable.Drawable;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.statemanager.StateManager;
|
||||
|
||||
/**
|
||||
* A DragView drawn/used by the Launcher activity.
|
||||
*/
|
||||
public class LauncherDragView extends DragView<Launcher>
|
||||
implements StateManager.StateListener<LauncherState> {
|
||||
|
||||
|
||||
public LauncherDragView(Launcher launcher, Drawable drawable, int registrationX,
|
||||
int registrationY, float initialScale, float scaleOnDrop, float finalScaleDps) {
|
||||
super(launcher, drawable, registrationX, registrationY, initialScale, scaleOnDrop,
|
||||
finalScaleDps);
|
||||
}
|
||||
|
||||
public LauncherDragView(Launcher launcher, View content, int width, int height,
|
||||
int registrationX, int registrationY, float initialScale, float scaleOnDrop,
|
||||
float finalScaleDps) {
|
||||
super(launcher, content, width, height, registrationX, registrationY, initialScale,
|
||||
scaleOnDrop, finalScaleDps);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
mActivity.getStateManager().addStateListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
mActivity.getStateManager().removeStateListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStateTransitionComplete(LauncherState finalState) {
|
||||
setVisibility((finalState == LauncherState.NORMAL
|
||||
|| finalState == LauncherState.SPRING_LOADED) ? VISIBLE : INVISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void animateTo(int toTouchX, int toTouchY, Runnable onCompleteRunnable, int duration) {
|
||||
mTempLoc[0] = toTouchX - mRegistrationX;
|
||||
mTempLoc[1] = toTouchY - mRegistrationY;
|
||||
mActivity.getDragLayer().animateViewIntoPosition(this, mTempLoc, 1f, mScaleOnDrop,
|
||||
mScaleOnDrop, DragLayer.ANIMATION_END_DISAPPEAR, onCompleteRunnable, duration);
|
||||
}
|
||||
}
|
||||
@@ -32,13 +32,13 @@ import android.view.View;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.dragndrop.DraggableView;
|
||||
import com.android.launcher3.icons.BitmapRenderer;
|
||||
import com.android.launcher3.icons.FastBitmapDrawable;
|
||||
import com.android.launcher3.util.SafeCloseable;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
import com.android.launcher3.widget.LauncherAppWidgetHostView;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
@@ -150,7 +150,7 @@ public class DragPreviewProvider {
|
||||
}
|
||||
|
||||
public float getScaleAndPosition(Drawable preview, int[] outPos) {
|
||||
float scale = Launcher.getLauncher(mView.getContext())
|
||||
float scale = ActivityContext.lookupContext(mView.getContext())
|
||||
.getDragLayer().getLocationInDragLayer(mView, outPos);
|
||||
if (mView instanceof LauncherAppWidgetHostView) {
|
||||
// App widgets are technically scaled, but are drawn at their expected size -- so the
|
||||
@@ -167,7 +167,7 @@ public class DragPreviewProvider {
|
||||
|
||||
/** Returns the scale and position of a given view for drag-n-drop. */
|
||||
public float getScaleAndPosition(View view, int[] outPos) {
|
||||
float scale = Launcher.getLauncher(mView.getContext())
|
||||
float scale = ActivityContext.lookupContext(mView.getContext())
|
||||
.getDragLayer().getLocationInDragLayer(mView, outPos);
|
||||
if (mView instanceof LauncherAppWidgetHostView) {
|
||||
// App widgets are technically scaled, but are drawn at their expected size -- so the
|
||||
@@ -201,7 +201,7 @@ public class DragPreviewProvider {
|
||||
public void run() {
|
||||
Bitmap preview = convertPreviewToAlphaBitmap(mPreviewSnapshot);
|
||||
if (mIsIcon) {
|
||||
int size = Launcher.getLauncher(mContext).getDeviceProfile().iconSizePx;
|
||||
int size = ActivityContext.lookupContext(mContext).getDeviceProfile().iconSizePx;
|
||||
preview = Bitmap.createScaledBitmap(preview, size, size, false);
|
||||
}
|
||||
//else case covers AppWidgetHost (doesn't drag/drop across different device profiles)
|
||||
|
||||
@@ -21,9 +21,12 @@ import android.graphics.Rect;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View.AccessibilityDelegate;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.dot.DotInfo;
|
||||
import com.android.launcher3.dragndrop.DragController;
|
||||
import com.android.launcher3.folder.FolderIcon;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.util.ViewCache;
|
||||
|
||||
@@ -99,6 +102,13 @@ public interface ActivityContext {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the FolderIcon with the given item id, if it exists.
|
||||
*/
|
||||
default @Nullable FolderIcon findFolderIcon(final int folderIconId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ActivityContext associated with the given Context.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user