Split PortraitOverviewStateTouchHelper for Go
Split out the logic in PortraitOverviewStateTouchHelper that is
dependent on the recents view implementation. This is done through a
separate helper class that we override on Go to stub out most of the
behavior.
This results in the Go version not supporting swipe transitions from
the recents state which is desired since we would otherwise risk
confusion over whether the swipe should go to the view or to the
transition (note that we will also take out the hotseat in this state).
Bug: 114136250
Test: Manual test NexusLauncher and l3goWithQuickstep
Test: Build l3goWithQuickstepIconRecents
Change-Id: I9b0e9c05171d279d03bbcb7f05344fa425f34b3e
diff --git a/go/quickstep/src/com/android/launcher3/uioverrides/PortraitOverviewStateTouchHelper.java b/go/quickstep/src/com/android/launcher3/uioverrides/PortraitOverviewStateTouchHelper.java
new file mode 100644
index 0000000..a3b41b0
--- /dev/null
+++ b/go/quickstep/src/com/android/launcher3/uioverrides/PortraitOverviewStateTouchHelper.java
@@ -0,0 +1,65 @@
+/*
+ * 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.launcher3.uioverrides;
+
+import android.view.MotionEvent;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.util.PendingAnimation;
+
+/**
+ * Helper class for {@link PortraitStatesTouchController} that determines swipeable regions and
+ * animations on the overview state that depend on the recents implementation.
+ */
+public final class PortraitOverviewStateTouchHelper {
+
+ public PortraitOverviewStateTouchHelper(Launcher launcher) {}
+
+ /**
+ * Whether or not {@link PortraitStatesTouchController} should intercept the touch when on the
+ * overview state.
+ *
+ * @param ev the motion event
+ * @return true if we should intercept the motion event
+ */
+ boolean canInterceptTouch(MotionEvent ev) {
+ // Go does not support swiping to all-apps from recents.
+ return false;
+ }
+
+ /**
+ * Whether or not swiping down to leave overview state should return to the currently running
+ * task app.
+ *
+ * @return true if going back should take the user to the currently running task
+ */
+ boolean shouldSwipeDownReturnToApp() {
+ // Go does not support swiping tasks down to launch tasks from recents.
+ return false;
+ }
+
+ /**
+ * Create the animation for going from overview to the task app via swiping.
+ *
+ * @param duration how long the animation should be
+ * @return the animation
+ */
+ PendingAnimation createSwipeDownToTaskAppAnimation(long duration) {
+ // Go does not support swiping tasks down to launch tasks from recents.
+ return null;
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/PortraitOverviewStateTouchHelper.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/PortraitOverviewStateTouchHelper.java
new file mode 100644
index 0000000..eead4c8
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/PortraitOverviewStateTouchHelper.java
@@ -0,0 +1,84 @@
+/*
+ * 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.launcher3.uioverrides;
+
+import static com.android.launcher3.uioverrides.PortraitStatesTouchController.isTouchOverHotseat;
+
+import android.view.MotionEvent;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.util.PendingAnimation;
+import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.TaskView;
+
+/**
+ * Helper class for {@link PortraitStatesTouchController} that determines swipeable regions and
+ * animations on the overview state that depend on the recents implementation.
+ */
+public final class PortraitOverviewStateTouchHelper {
+
+ RecentsView mRecentsView;
+ Launcher mLauncher;
+
+ public PortraitOverviewStateTouchHelper(Launcher launcher) {
+ mLauncher = launcher;
+ mRecentsView = launcher.getOverviewPanel();
+ }
+
+ /**
+ * Whether or not {@link PortraitStatesTouchController} should intercept the touch when on the
+ * overview state.
+ *
+ * @param ev the motion event
+ * @return true if we should intercept the motion event
+ */
+ boolean canInterceptTouch(MotionEvent ev) {
+ if (mRecentsView.getChildCount() > 0) {
+ // Allow swiping up in the gap between the hotseat and overview.
+ return ev.getY() >= mRecentsView.getChildAt(0).getBottom();
+ } else {
+ // If there are no tasks, we only intercept if we're below the hotseat height.
+ return isTouchOverHotseat(mLauncher, ev);
+ }
+ }
+
+ /**
+ * Whether or not swiping down to leave overview state should return to the currently running
+ * task app.
+ *
+ * @return true if going back should take the user to the currently running task
+ */
+ boolean shouldSwipeDownReturnToApp() {
+ TaskView taskView = mRecentsView.getTaskViewAt(mRecentsView.getNextPage());
+ return taskView != null && mRecentsView.shouldSwipeDownLaunchApp();
+ }
+
+ /**
+ * Create the animation for going from overview to the task app via swiping. Should only be
+ * called when {@link #shouldSwipeDownReturnToApp()} returns true.
+ *
+ * @param duration how long the animation should be
+ * @return the animation
+ */
+ PendingAnimation createSwipeDownToTaskAppAnimation(long duration) {
+ TaskView taskView = mRecentsView.getTaskViewAt(mRecentsView.getNextPage());
+ if (taskView == null) {
+ throw new IllegalStateException("There is no task view to animate to.");
+ }
+ return mRecentsView.createTaskLauncherAnimation(taskView, duration);
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java
index 8684c58..84b9853 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java
@@ -47,8 +47,6 @@
import com.android.quickstep.RecentsModel;
import com.android.quickstep.TouchInteractionService;
import com.android.quickstep.util.LayoutUtils;
-import com.android.quickstep.views.RecentsView;
-import com.android.quickstep.views.TaskView;
/**
* Touch controller for handling various state transitions in portrait UI.
@@ -67,14 +65,16 @@
*/
private static final float RECENTS_FADE_THRESHOLD = 0.88f;
+ private final PortraitOverviewStateTouchHelper mOverviewPortraitStateTouchHelper;
+
private InterpolatorWrapper mAllAppsInterpolatorWrapper = new InterpolatorWrapper();
// If true, we will finish the current animation instantly on second touch.
private boolean mFinishFastOnSecondTouch;
-
public PortraitStatesTouchController(Launcher l) {
super(l, SwipeDetector.VERTICAL);
+ mOverviewPortraitStateTouchHelper = new PortraitOverviewStateTouchHelper(l);
}
@Override
@@ -98,22 +98,18 @@
}
return false;
}
- RecentsView recentsView = mLauncher.getOverviewPanel();
if (mLauncher.isInState(ALL_APPS)) {
// In all-apps only listen if the container cannot scroll itself
if (!mLauncher.getAppsView().shouldContainerScroll(ev)) {
return false;
}
- } else if (mLauncher.isInState(OVERVIEW) && recentsView.getChildCount() > 0) {
- // Allow swiping up in the gap between the hotseat and overview.
- if (ev.getY() < recentsView.getChildAt(0).getBottom()) {
+ } else if (mLauncher.isInState(OVERVIEW)) {
+ if (!mOverviewPortraitStateTouchHelper.canInterceptTouch(ev)) {
return false;
}
} else {
// For all other states, only listen if the event originated below the hotseat height
- DeviceProfile dp = mLauncher.getDeviceProfile();
- int hotseatHeight = dp.hotseatBarSizePx + dp.getInsets().bottom;
- if (ev.getY() < (mLauncher.getDragLayer().getHeight() - hotseatHeight)) {
+ if (!isTouchOverHotseat(mLauncher, ev)) {
return false;
}
}
@@ -197,13 +193,12 @@
cancelPendingAnim();
- RecentsView recentsView = mLauncher.getOverviewPanel();
- TaskView taskView = recentsView.getTaskViewAt(recentsView.getNextPage());
- if (recentsView.shouldSwipeDownLaunchApp() && mFromState == OVERVIEW && mToState == NORMAL
- && taskView != null) {
+ if (mFromState == OVERVIEW && mToState == NORMAL
+ && mOverviewPortraitStateTouchHelper.shouldSwipeDownReturnToApp()) {
// Reset the state manager, when changing the interaction mode
mLauncher.getStateManager().goToState(OVERVIEW, false /* animate */);
- mPendingAnimation = recentsView.createTaskLauncherAnimation(taskView, maxAccuracy);
+ mPendingAnimation = mOverviewPortraitStateTouchHelper
+ .createSwipeDownToTaskAppAnimation(maxAccuracy);
mPendingAnimation.anim.setInterpolator(Interpolators.LINEAR);
Runnable onCancelRunnable = () -> {
@@ -268,6 +263,19 @@
}
}
+ /**
+ * Whether the motion event is over the hotseat.
+ *
+ * @param launcher the launcher activity
+ * @param ev the event to check
+ * @return true if the event is over the hotseat
+ */
+ static boolean isTouchOverHotseat(Launcher launcher, MotionEvent ev) {
+ DeviceProfile dp = launcher.getDeviceProfile();
+ int hotseatHeight = dp.hotseatBarSizePx + dp.getInsets().bottom;
+ return (ev.getY() >= (launcher.getDragLayer().getHeight() - hotseatHeight));
+ }
+
private static class InterpolatorWrapper implements Interpolator {
public TimeInterpolator baseInterpolator = LINEAR;