Merge "Removing fade animation on swipe up" into ub-launcher3-master
diff --git a/go/quickstep/res/layout/task_item_view.xml b/go/quickstep/res/layout/task_item_view.xml
index 90940c4..ee67d49 100644
--- a/go/quickstep/res/layout/task_item_view.xml
+++ b/go/quickstep/res/layout/task_item_view.xml
@@ -19,12 +19,24 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
- <ImageView
+ <FrameLayout
android:id="@+id/task_icon_and_thumbnail"
- android:layout_width="@dimen/task_thumbnail_icon_size"
- android:layout_height="@dimen/task_thumbnail_icon_size"
+ android:layout_width="@dimen/task_item_height"
+ android:layout_height="@dimen/task_item_height"
android:layout_gravity="center_vertical"
- android:layout_marginHorizontal="8dp"/>
+ android:layout_marginHorizontal="8dp"
+ android:layout_marginVertical="@dimen/task_item_half_vert_margin">
+ <ImageView
+ android:id="@+id/task_thumbnail"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_gravity="top|start"/>
+ <ImageView
+ android:id="@+id/task_icon"
+ android:layout_width="@dimen/task_icon_size"
+ android:layout_height="@dimen/task_icon_size"
+ android:layout_gravity="bottom|end"/>
+ </FrameLayout>
<TextView
android:id="@+id/task_label"
android:layout_width="wrap_content"
diff --git a/go/quickstep/res/values/dimens.xml b/go/quickstep/res/values/dimens.xml
new file mode 100644
index 0000000..28cc1eb
--- /dev/null
+++ b/go/quickstep/res/values/dimens.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 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.
+-->
+<resources>
+ <dimen name="task_item_height">60dp</dimen>
+ <dimen name="task_item_half_vert_margin">8dp</dimen>
+ <dimen name="task_icon_size">36dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/go/quickstep/src/com/android/quickstep/TaskAdapter.java b/go/quickstep/src/com/android/quickstep/TaskAdapter.java
index 99446d0..4f3d1e4 100644
--- a/go/quickstep/src/com/android/quickstep/TaskAdapter.java
+++ b/go/quickstep/src/com/android/quickstep/TaskAdapter.java
@@ -25,7 +25,8 @@
import com.android.quickstep.views.TaskItemView;
import com.android.systemui.shared.recents.model.Task;
-import java.util.ArrayList;
+import java.util.List;
+
/**
* Recycler view adapter that dynamically inflates and binds {@link TaskHolder} instances with the
* appropriate {@link Task} from the recents task list.
@@ -56,7 +57,7 @@
@Override
public void onBindViewHolder(TaskHolder holder, int position) {
- ArrayList<Task> tasks = mLoader.getCurrentTaskList();
+ List<Task> tasks = mLoader.getCurrentTaskList();
if (position >= tasks.size()) {
// Task list has updated.
return;
diff --git a/go/quickstep/src/com/android/quickstep/TaskHolder.java b/go/quickstep/src/com/android/quickstep/TaskHolder.java
index 67e8ece..8d5e4d5 100644
--- a/go/quickstep/src/com/android/quickstep/TaskHolder.java
+++ b/go/quickstep/src/com/android/quickstep/TaskHolder.java
@@ -45,6 +45,7 @@
mTask = task;
mTaskItemView.setLabel(task.titleDescription);
mTaskItemView.setIcon(task.icon);
+ mTaskItemView.setThumbnail(task.thumbnail.thumbnail);
}
/**
diff --git a/go/quickstep/src/com/android/quickstep/TaskInputController.java b/go/quickstep/src/com/android/quickstep/TaskInputController.java
index 66c4496..d97ac8d 100644
--- a/go/quickstep/src/com/android/quickstep/TaskInputController.java
+++ b/go/quickstep/src/com/android/quickstep/TaskInputController.java
@@ -15,6 +15,7 @@
*/
package com.android.quickstep;
+import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.ActivityManagerWrapper;
/**
@@ -22,9 +23,11 @@
*/
public final class TaskInputController {
- TaskAdapter mAdapter;
+ private final TaskListLoader mLoader;
+ private final TaskAdapter mAdapter;
- public TaskInputController(TaskAdapter adapter) {
+ public TaskInputController(TaskListLoader loader,TaskAdapter adapter) {
+ mLoader = loader;
mAdapter = adapter;
}
@@ -39,7 +42,14 @@
null /* options */, null /* resultCallback */, null /* resultCallbackHandler */);
}
- // TODO: Implement swipe to delete and notify adapter that data has updated
+ public void onTaskSwiped(TaskHolder viewHolder) {
+ int position = viewHolder.getAdapterPosition();
+ Task task = viewHolder.getTask();
+ ActivityManagerWrapper.getInstance().removeTask(task.key.id);
+ mLoader.removeTask(task);
+ mAdapter.notifyItemRemoved(position);
+ }
// TODO: Implement "Clear all" and notify adapter that data has updated
+
}
diff --git a/go/quickstep/src/com/android/quickstep/TaskListLoader.java b/go/quickstep/src/com/android/quickstep/TaskListLoader.java
index c798cef..e6d1a22 100644
--- a/go/quickstep/src/com/android/quickstep/TaskListLoader.java
+++ b/go/quickstep/src/com/android/quickstep/TaskListLoader.java
@@ -24,6 +24,7 @@
import java.util.ArrayList;
import java.util.Collections;
+import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
@@ -45,13 +46,13 @@
/**
* Returns the current task list as of the last completed load (see
- * {@link #loadTaskList}). This list of tasks is guaranteed to always have all its task
- * content loaded.
+ * {@link #loadTaskList}) as a read-only list. This list of tasks is guaranteed to always have
+ * all its task content loaded.
*
* @return the current list of tasks w/ all content loaded
*/
- public ArrayList<Task> getCurrentTaskList() {
- return mTaskList;
+ public List<Task> getCurrentTaskList() {
+ return Collections.unmodifiableList(mTaskList);
}
/**
@@ -85,6 +86,13 @@
}
/**
+ * Removes the task from the current task list.
+ */
+ void removeTask(Task task) {
+ mTaskList.remove(task);
+ }
+
+ /**
* Loads task content for a list of tasks, including the label, icon, and thumbnail. For content
* that isn't cached, load the content asynchronously in the background.
*
diff --git a/go/quickstep/src/com/android/quickstep/TaskSwipeCallback.java b/go/quickstep/src/com/android/quickstep/TaskSwipeCallback.java
new file mode 100644
index 0000000..2a53917
--- /dev/null
+++ b/go/quickstep/src/com/android/quickstep/TaskSwipeCallback.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 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.quickstep;
+
+import static androidx.recyclerview.widget.ItemTouchHelper.RIGHT;
+
+import androidx.recyclerview.widget.ItemTouchHelper;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.ViewHolder;
+
+/**
+ * Callback for swipe input on {@link TaskHolder} views in the recents view.
+ */
+public final class TaskSwipeCallback extends ItemTouchHelper.SimpleCallback {
+
+ private final TaskInputController mTaskInputController;
+
+ public TaskSwipeCallback(TaskInputController inputController) {
+ super(0 /* dragDirs */, RIGHT);
+ mTaskInputController = inputController;
+ }
+
+ @Override
+ public boolean onMove(RecyclerView recyclerView, ViewHolder viewHolder,
+ ViewHolder target) {
+ return false;
+ }
+
+ @Override
+ public void onSwiped(ViewHolder viewHolder, int direction) {
+ if (direction == RIGHT) {
+ mTaskInputController.onTaskSwiped((TaskHolder) viewHolder);
+ }
+ }
+}
diff --git a/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java b/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java
index e8a915f..b7740eb 100644
--- a/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java
+++ b/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java
@@ -23,6 +23,7 @@
import android.view.ViewDebug;
import android.widget.FrameLayout;
+import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@@ -30,6 +31,7 @@
import com.android.quickstep.TaskAdapter;
import com.android.quickstep.TaskInputController;
import com.android.quickstep.TaskListLoader;
+import com.android.quickstep.TaskSwipeCallback;
/**
* Root view for the icon recents view. Acts as the main interface to the rest of the Launcher code
@@ -76,29 +78,35 @@
@ViewDebug.ExportedProperty(category = "launcher")
private final Context mContext;
+ private final TaskListLoader mTaskLoader;
+ private final TaskAdapter mTaskAdapter;
+ private final TaskInputController mTaskInputController;
private float mTranslationYFactor;
- private TaskAdapter mTaskAdapter;
private RecyclerView mTaskRecyclerView;
- private TaskInputController mTaskInputController;
- private TaskListLoader mTaskLoader;
+
public IconRecentsView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
+ mTaskLoader = new TaskListLoader(mContext);
+ mTaskAdapter = new TaskAdapter(mTaskLoader);
+ mTaskInputController = new TaskInputController(mTaskLoader, mTaskAdapter);
+ mTaskAdapter.setInputController(mTaskInputController);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mTaskLoader = new TaskListLoader(mContext);
- mTaskAdapter = new TaskAdapter(mTaskLoader);
- mTaskInputController = new TaskInputController(mTaskAdapter);
- mTaskAdapter.setInputController(mTaskInputController);
- mTaskRecyclerView = findViewById(R.id.recent_task_recycler_view);
- mTaskRecyclerView.setAdapter(mTaskAdapter);
- mTaskRecyclerView.setLayoutManager(
- new LinearLayoutManager(mContext, VERTICAL, true /* reverseLayout */));
+ if (mTaskRecyclerView == null) {
+ mTaskRecyclerView = findViewById(R.id.recent_task_recycler_view);
+ mTaskRecyclerView.setAdapter(mTaskAdapter);
+ mTaskRecyclerView.setLayoutManager(
+ new LinearLayoutManager(mContext, VERTICAL, true /* reverseLayout */));
+ ItemTouchHelper helper = new ItemTouchHelper(
+ new TaskSwipeCallback(mTaskInputController));
+ helper.attachToRecyclerView(mTaskRecyclerView);
+ }
}
/**
diff --git a/go/quickstep/src/com/android/quickstep/views/TaskItemView.java b/go/quickstep/src/com/android/quickstep/views/TaskItemView.java
index ce3947d..3818965 100644
--- a/go/quickstep/src/com/android/quickstep/views/TaskItemView.java
+++ b/go/quickstep/src/com/android/quickstep/views/TaskItemView.java
@@ -16,6 +16,7 @@
package com.android.quickstep.views;
import android.content.Context;
+import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;
@@ -31,6 +32,7 @@
private TextView mLabelView;
private ImageView mIconView;
+ private ImageView mThumbnailView;
public TaskItemView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -40,7 +42,8 @@
protected void onFinishInflate() {
super.onFinishInflate();
mLabelView = findViewById(R.id.task_label);
- mIconView = findViewById(R.id.task_icon_and_thumbnail);
+ mThumbnailView = findViewById(R.id.task_thumbnail);
+ mIconView = findViewById(R.id.task_icon);
}
/**
@@ -58,7 +61,19 @@
* @param icon task icon
*/
public void setIcon(Drawable icon) {
+ // TODO: Scale the icon up based off the padding on the side
+ // The icon proper is actually smaller than the drawable and has "padding" on the side for
+ // the purpose of drawing the shadow, allowing the icon to pop up, so we need to scale the
+ // view if we want the icon to be flush with the bottom of the thumbnail.
mIconView.setImageDrawable(icon);
- // TODO: Add in combination drawable for icon + thumbnail
+ }
+
+ /**
+ * Set the task thumbnail for the task.
+ *
+ * @param thumbnail task thumbnail for the task
+ */
+ public void setThumbnail(Bitmap thumbnail) {
+ mThumbnailView.setImageBitmap(thumbnail);
}
}
diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml
index 0992849..62d0500 100644
--- a/quickstep/AndroidManifest.xml
+++ b/quickstep/AndroidManifest.xml
@@ -39,7 +39,7 @@
<service
android:name="com.android.quickstep.TouchInteractionService"
android:permission="android.permission.STATUS_BAR_SERVICE"
- android:directBootAware="false" >
+ android:directBootAware="true" >
<intent-filter>
<action android:name="android.intent.action.QUICKSTEP_SERVICE" />
</intent-filter>
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/OverviewState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/OverviewState.java
index 3602508..f4ea9f9 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/OverviewState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/OverviewState.java
@@ -18,6 +18,7 @@
import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
+import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
import static com.android.launcher3.states.RotationHelper.REQUEST_ROTATE;
import android.graphics.Rect;
@@ -30,8 +31,8 @@
import com.android.launcher3.R;
import com.android.launcher3.Workspace;
import com.android.launcher3.allapps.DiscoveryBounce;
+import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
-import com.android.quickstep.RecentsModel;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
@@ -139,6 +140,8 @@
public void onBackPressed(Launcher launcher) {
TaskView taskView = launcher.<RecentsView>getOverviewPanel().getRunningTaskView();
if (taskView != null) {
+ launcher.getUserEventDispatcher().logActionCommand(Action.Command.BACK,
+ newContainerTarget(ContainerType.OVERVIEW));
taskView.launchTask(true);
} else {
super.onBackPressed(launcher);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
index 2583ffb..252a957 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
@@ -1578,7 +1578,9 @@
}
public void updateLiveTileIcon(Drawable icon) {
- mLiveTileOverlay.setIcon(icon);
+ if (mLiveTileOverlay != null) {
+ mLiveTileOverlay.setIcon(icon);
+ }
}
public void finishRecentsAnimation(boolean toRecents, Runnable onFinishComplete) {
diff --git a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
index fe789aa..6031dcd 100644
--- a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
+++ b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
@@ -37,6 +37,9 @@
@LargeTest
@RunWith(AndroidJUnit4.class)
public class StartLauncherViaGestureTests extends AbstractQuickStepTest {
+
+ static final int STRESS_REPEAT_COUNT = 10;
+
@Override
@Before
public void setUp() throws Exception {
@@ -79,4 +82,28 @@
closeLauncherActivity();
mLauncher.getBackground().switchToOverview();
}
+
+ @Test
+ @QuickstepOnOff
+ public void testStressPressHome() {
+ for (int i = 0; i < STRESS_REPEAT_COUNT; ++i) {
+ // Destroy Launcher activity.
+ closeLauncherActivity();
+
+ // The test action.
+ mLauncher.pressHome();
+ }
+ }
+
+ @Test
+ @QuickstepOnOff
+ public void testStressSwipeToOverview() {
+ for (int i = 0; i < STRESS_REPEAT_COUNT; ++i) {
+ // Destroy Launcher activity.
+ closeLauncherActivity();
+
+ // The test action.
+ mLauncher.getBackground().switchToOverview();
+ }
+ }
}
\ No newline at end of file
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index e699500..7036639 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -571,9 +571,11 @@
final boolean isFolderIcon = v instanceof FolderIcon;
final Rect rect = new Rect();
+ // Deep shortcut views have their icon drawn in a separate view.
final boolean fromDeepShortcutView = v.getParent() instanceof DeepShortcutView;
- if (fromDeepShortcutView) {
- // Deep shortcut views have their icon drawn in a separate view.
+ if (v instanceof DeepShortcutView) {
+ dragLayer.getDescendantRectRelativeToSelf(((DeepShortcutView) v).getIconView(), rect);
+ } else if (fromDeepShortcutView) {
DeepShortcutView view = (DeepShortcutView) v.getParent();
dragLayer.getDescendantRectRelativeToSelf(view.getIconView(), rect);
} else if ((isBubbleTextView || isFolderIcon) && v.getTag() instanceof ItemInfo
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 09eb6d9..9427675 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -3084,6 +3084,10 @@
}
private boolean mapOverCellLayout(boolean recurse, CellLayout layout, ItemOperator op) {
+ // TODO(b/128460496) Potential race condition where layout is not yet loaded
+ if (layout == null) {
+ return false;
+ }
ShortcutAndWidgetContainer container = layout.getShortcutsAndWidgets();
// map over all the shortcuts on the workspace
final int itemCount = container.getChildCount();
diff --git a/src/com/android/launcher3/dragndrop/FolderAdaptiveIcon.java b/src/com/android/launcher3/dragndrop/FolderAdaptiveIcon.java
index 5e41bb7..0c5a1fc 100644
--- a/src/com/android/launcher3/dragndrop/FolderAdaptiveIcon.java
+++ b/src/com/android/launcher3/dragndrop/FolderAdaptiveIcon.java
@@ -19,11 +19,8 @@
import android.annotation.TargetApi;
import android.graphics.Bitmap;
import android.graphics.Canvas;
-import android.graphics.ColorFilter;
import android.graphics.Matrix;
-import android.graphics.Paint;
import android.graphics.Path;
-import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.ColorDrawable;
@@ -49,11 +46,15 @@
private final Drawable mBadge;
private final Path mMask;
+ private final ConstantState mConstantState;
private FolderAdaptiveIcon(Drawable bg, Drawable fg, Drawable badge, Path mask) {
super(bg, fg);
mBadge = badge;
mMask = mask;
+
+ mConstantState = new MyConstantState(bg.getConstantState(), fg.getConstantState(),
+ badge.getConstantState(), mask);
}
@Override
@@ -134,4 +135,35 @@
return new FolderAdaptiveIcon(new ColorDrawable(bg.getBgColor()), foreground, badge, mask);
}
+
+ @Override
+ public ConstantState getConstantState() {
+ return mConstantState;
+ }
+
+ private static class MyConstantState extends ConstantState {
+ private final ConstantState mBg;
+ private final ConstantState mFg;
+ private final ConstantState mBadge;
+ private final Path mMask;
+
+ MyConstantState(ConstantState bg, ConstantState fg, ConstantState badge, Path mask) {
+ mBg = bg;
+ mFg = fg;
+ mBadge = badge;
+ mMask = mask;
+ }
+
+ @Override
+ public Drawable newDrawable() {
+ return new FolderAdaptiveIcon(mBg.newDrawable(), mFg.newDrawable(),
+ mBadge.newDrawable(), mMask);
+ }
+
+ @Override
+ public int getChangingConfigurations() {
+ return mBg.getChangingConfigurations() & mFg.getChangingConfigurations()
+ & mBadge.getChangingConfigurations();
+ }
+ }
}
diff --git a/src/com/android/launcher3/graphics/ShiftedBitmapDrawable.java b/src/com/android/launcher3/graphics/ShiftedBitmapDrawable.java
index 52d45bb..f8583b8 100644
--- a/src/com/android/launcher3/graphics/ShiftedBitmapDrawable.java
+++ b/src/com/android/launcher3/graphics/ShiftedBitmapDrawable.java
@@ -32,10 +32,14 @@
private float mShiftX;
private float mShiftY;
+ private final ConstantState mConstantState;
+
public ShiftedBitmapDrawable(Bitmap bitmap, float shiftX, float shiftY) {
mBitmap = bitmap;
mShiftX = shiftX;
mShiftY = shiftY;
+
+ mConstantState = new MyConstantState(mBitmap, mShiftX, mShiftY);
}
public float getShiftX() {
@@ -71,4 +75,31 @@
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
+
+ @Override
+ public ConstantState getConstantState() {
+ return mConstantState;
+ }
+
+ private static class MyConstantState extends ConstantState {
+ private final Bitmap mBitmap;
+ private float mShiftX;
+ private float mShiftY;
+
+ MyConstantState(Bitmap bitmap, float shiftX, float shiftY) {
+ mBitmap = bitmap;
+ mShiftX = shiftX;
+ mShiftY = shiftY;
+ }
+
+ @Override
+ public Drawable newDrawable() {
+ return new ShiftedBitmapDrawable(mBitmap, mShiftX, mShiftY);
+ }
+
+ @Override
+ public int getChangingConfigurations() {
+ return 0;
+ }
+ }
}
\ No newline at end of file
diff --git a/src/com/android/launcher3/touch/WorkspaceTouchListener.java b/src/com/android/launcher3/touch/WorkspaceTouchListener.java
index 4de082e..7801756 100644
--- a/src/com/android/launcher3/touch/WorkspaceTouchListener.java
+++ b/src/com/android/launcher3/touch/WorkspaceTouchListener.java
@@ -29,6 +29,7 @@
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
+import android.view.GestureDetector;
import android.view.View.OnTouchListener;
import android.view.ViewConfiguration;
@@ -45,7 +46,7 @@
/**
* Helper class to handle touch on empty space in workspace and show options popup on long press
*/
-public class WorkspaceTouchListener implements OnTouchListener, Runnable {
+public class WorkspaceTouchListener extends GestureDetector.SimpleOnGestureListener implements OnTouchListener {
/**
* STATE_PENDING_PARENT_INFORM is the state between longPress performed & the next motionEvent.
@@ -66,16 +67,21 @@
private int mLongPressState = STATE_CANCELLED;
+ private final GestureDetector mGestureDetector;
+
public WorkspaceTouchListener(Launcher launcher, Workspace workspace) {
mLauncher = launcher;
mWorkspace = workspace;
// Use twice the touch slop as we are looking for long press which is more
// likely to cause movement.
mTouchSlop = 2 * ViewConfiguration.get(launcher).getScaledTouchSlop();
+ mGestureDetector = new GestureDetector(workspace.getContext(), this);
}
@Override
public boolean onTouch(View view, MotionEvent ev) {
+ mGestureDetector.onTouchEvent(ev);
+
int action = ev.getActionMasked();
if (action == ACTION_DOWN) {
// Check if we can handle long press.
@@ -97,7 +103,6 @@
if (handleLongPress) {
mLongPressState = STATE_REQUESTED;
mTouchDownPoint.set(ev.getX(), ev.getY());
- mWorkspace.postDelayed(this, getLongPressTimeout());
}
mWorkspace.onTouchEvent(ev);
@@ -155,12 +160,11 @@
}
private void cancelLongPress() {
- mWorkspace.removeCallbacks(this);
mLongPressState = STATE_CANCELLED;
}
@Override
- public void run() {
+ public void onLongPress(MotionEvent event) {
if (mLongPressState == STATE_REQUESTED) {
if (canHandleLongPress()) {
mLongPressState = STATE_PENDING_PARENT_INFORM;
diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java
index 5163e5f..e5c70da 100644
--- a/src/com/android/launcher3/views/FloatingIconView.java
+++ b/src/com/android/launcher3/views/FloatingIconView.java
@@ -50,6 +50,7 @@
import com.android.launcher3.graphics.ShiftedBitmapDrawable;
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.popup.SystemShortcut;
+import com.android.launcher3.shortcuts.DeepShortcutView;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
@@ -67,7 +68,6 @@
private Runnable mStartRunnable;
private Runnable mEndRunnable;
- private Drawable mDrawable;
private int mOriginalHeight;
private final int mBlurSizeOutline;
@@ -191,73 +191,85 @@
private void getIcon(Launcher launcher, View v, ItemInfo info, boolean useDrawableAsIs,
float aspectRatio) {
final LayoutParams lp = (LayoutParams) getLayoutParams();
-
+ Drawable drawable = null;
boolean supportsAdaptiveIcons = ADAPTIVE_ICON_WINDOW_ANIM.get() && !useDrawableAsIs
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
if (!supportsAdaptiveIcons && v instanceof BubbleTextView) {
// Similar to DragView, we simply use the BubbleTextView icon here.
- mDrawable = ((BubbleTextView) v).getIcon();
+ drawable = ((BubbleTextView) v).getIcon();
}
- if (v instanceof ImageView && info instanceof SystemShortcut) {
- mDrawable = ((ImageView) v).getDrawable();
+ if (info instanceof SystemShortcut) {
+ if (v instanceof ImageView) {
+ drawable = ((ImageView) v).getDrawable();
+ } else if (v instanceof DeepShortcutView) {
+ drawable = ((DeepShortcutView) v).getIconView().getBackground();
+ } else {
+ drawable = v.getBackground();
+ }
}
- if (mDrawable == null) {
- mDrawable = Utilities.getFullDrawable(launcher, info, lp.width, lp.height,
+ if (drawable == null) {
+ drawable = Utilities.getFullDrawable(launcher, info, lp.width, lp.height,
useDrawableAsIs, new Object[1]);
}
- if (supportsAdaptiveIcons && mDrawable instanceof AdaptiveIconDrawable) {
- mIsAdaptiveIcon = true;
-
- AdaptiveIconDrawable adaptiveIcon = (AdaptiveIconDrawable) mDrawable;
- Drawable background = adaptiveIcon.getBackground();
- if (background == null) {
- background = new ColorDrawable(Color.TRANSPARENT);
- }
- mBackground = background;
- Drawable foreground = adaptiveIcon.getForeground();
- if (foreground == null) {
- foreground = new ColorDrawable(Color.TRANSPARENT);
- }
- mForeground = foreground;
-
- int offset = getOffsetForAdaptiveIconBounds();
- mFinalDrawableBounds.set(offset, offset, lp.width - offset, mOriginalHeight - offset);
- if (mForeground instanceof ShiftedBitmapDrawable && v instanceof FolderIcon) {
- ShiftedBitmapDrawable sbd = (ShiftedBitmapDrawable) mForeground;
- ((FolderIcon) v).getPreviewBounds(sTmpRect);
- sbd.setShiftX(sbd.getShiftX() - sTmpRect.left);
- sbd.setShiftY(sbd.getShiftY() - sTmpRect.top);
- }
- mForeground.setBounds(mFinalDrawableBounds);
- mBackground.setBounds(mFinalDrawableBounds);
-
- int blurMargin = mBlurSizeOutline / 2;
- mStartRevealRect.set(blurMargin, blurMargin , lp.width - blurMargin,
- mOriginalHeight - blurMargin);
-
- if (aspectRatio > 0) {
- lp.height = (int) Math.max(lp.height, lp.width * aspectRatio);
- layout(lp.leftMargin, lp.topMargin, lp.leftMargin + lp.width, lp.topMargin
- + lp.height);
- }
- mBgDrawableStartScale = (float) lp.height / mOriginalHeight;
- setBackgroundDrawableBounds(mBgDrawableStartScale);
-
- // Set up outline
- mOutline.set(0, 0, lp.width, lp.height);
- setOutlineProvider(new ViewOutlineProvider() {
- @Override
- public void getOutline(View view, Outline outline) {
- outline.setRoundRect(mOutline, mTaskCornerRadius);
- }
- });
- setClipToOutline(true);
- } else {
- setBackground(mDrawable);
- }
+ Drawable finalDrawable = drawable == null ? null
+ : drawable.getConstantState().newDrawable();
+ boolean isAdaptiveIcon = supportsAdaptiveIcons
+ && finalDrawable instanceof AdaptiveIconDrawable;
+ int iconOffset = getOffsetForIconBounds(finalDrawable);
new Handler(Looper.getMainLooper()).post(() -> {
+ if (isAdaptiveIcon) {
+ mIsAdaptiveIcon = true;
+
+ AdaptiveIconDrawable adaptiveIcon = (AdaptiveIconDrawable) finalDrawable;
+ Drawable background = adaptiveIcon.getBackground();
+ if (background == null) {
+ background = new ColorDrawable(Color.TRANSPARENT);
+ }
+ mBackground = background;
+ Drawable foreground = adaptiveIcon.getForeground();
+ if (foreground == null) {
+ foreground = new ColorDrawable(Color.TRANSPARENT);
+ }
+ mForeground = foreground;
+
+ mFinalDrawableBounds.set(iconOffset, iconOffset, lp.width -
+ iconOffset, mOriginalHeight - iconOffset);
+ if (mForeground instanceof ShiftedBitmapDrawable && v instanceof FolderIcon) {
+ ShiftedBitmapDrawable sbd = (ShiftedBitmapDrawable) mForeground;
+ ((FolderIcon) v).getPreviewBounds(sTmpRect);
+ sbd.setShiftX(sbd.getShiftX() - sTmpRect.left);
+ sbd.setShiftY(sbd.getShiftY() - sTmpRect.top);
+ }
+ mForeground.setBounds(mFinalDrawableBounds);
+ mBackground.setBounds(mFinalDrawableBounds);
+
+ int blurMargin = mBlurSizeOutline / 2;
+ mStartRevealRect.set(blurMargin, blurMargin , lp.width - blurMargin,
+ mOriginalHeight - blurMargin);
+
+ if (aspectRatio > 0) {
+ lp.height = (int) Math.max(lp.height, lp.width * aspectRatio);
+ layout(lp.leftMargin, lp.topMargin, lp.leftMargin + lp.width, lp.topMargin
+ + lp.height);
+ }
+ mBgDrawableStartScale = (float) lp.height / mOriginalHeight;
+ setBackgroundDrawableBounds(mBgDrawableStartScale);
+
+ // Set up outline
+ mOutline.set(0, 0, lp.width, lp.height);
+ setOutlineProvider(new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ outline.setRoundRect(mOutline, mTaskCornerRadius);
+ }
+ });
+ setClipToOutline(true);
+ } else {
+ setBackground(finalDrawable);
+ }
+
invalidate();
invalidateOutline();
});
@@ -272,9 +284,10 @@
mBackground.setBounds(mBgDrawableBounds);
}
- private int getOffsetForAdaptiveIconBounds() {
+ @WorkerThread
+ private int getOffsetForIconBounds(Drawable drawable) {
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.O ||
- !(mDrawable instanceof AdaptiveIconDrawable)) {
+ !(drawable instanceof AdaptiveIconDrawable)) {
return 0;
}
@@ -283,7 +296,7 @@
bounds.inset(mBlurSizeOutline / 2, mBlurSizeOutline / 2);
try (LauncherIcons li = LauncherIcons.obtain(Launcher.fromContext(getContext()))) {
- Utilities.scaleRectAboutCenter(bounds, li.getNormalizer().getScale(mDrawable, null));
+ Utilities.scaleRectAboutCenter(bounds, li.getNormalizer().getScale(drawable, null));
}
bounds.inset(