From 69d05656c64b1b6b2f29fb23e6dd186c8caf03cb Mon Sep 17 00:00:00 2001 From: Kevin Date: Wed, 16 Jan 2019 10:57:04 -0800 Subject: [PATCH] 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 --- .../PortraitOverviewStateTouchHelper.java | 65 ++++++++++++++ .../PortraitOverviewStateTouchHelper.java | 84 +++++++++++++++++++ .../PortraitStatesTouchController.java | 38 +++++---- 3 files changed, 172 insertions(+), 15 deletions(-) create mode 100644 go/quickstep/src/com/android/launcher3/uioverrides/PortraitOverviewStateTouchHelper.java create mode 100644 quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/PortraitOverviewStateTouchHelper.java 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 0000000000..a3b41b02f2 --- /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 0000000000..eead4c8ba3 --- /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 8684c58f1d..84b985353c 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.launcher3.userevent.nano.LauncherLogProto.ContainerType; 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 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr */ 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 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr } 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 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr 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 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr } } + /** + * 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;