diff --git a/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java index bdbdd8f76e..0c34b45302 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java @@ -32,12 +32,16 @@ import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; +import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.AnimatorSetBuilder; +import com.android.launcher3.anim.Interpolators; import com.android.launcher3.touch.AbstractStateChangeTouchController; import com.android.launcher3.touch.SwipeDetector; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.quickstep.TouchInteractionService; import com.android.quickstep.util.SysuiEventLogger; +import com.android.quickstep.views.RecentsView; +import com.android.quickstep.views.TaskView; /** * Touch controller for handling various state transitions in portrait UI. @@ -191,8 +195,23 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr mClampProgressUpdate = -1; } - mCurrentAnimation = mLauncher.getStateManager() - .createAnimationToNewWorkspace(mToState, builder, maxAccuracy); + if (mPendingAnimation != null) { + mPendingAnimation.finish(false); + mPendingAnimation = null; + } + + RecentsView recentsView = mLauncher.getOverviewPanel(); + TaskView taskView = (TaskView) recentsView.getChildAt(recentsView.getNextPage()); + if (recentsView.shouldSwipeDownLaunchApp() && mFromState == OVERVIEW && mToState == NORMAL + && taskView != null) { + mPendingAnimation = recentsView.createTaskLauncherAnimation(taskView, maxAccuracy); + mPendingAnimation.anim.setInterpolator(Interpolators.ZOOM_IN); + + mCurrentAnimation = AnimatorPlaybackController.wrap(mPendingAnimation.anim, maxAccuracy); + } else { + mCurrentAnimation = mLauncher.getStateManager() + .createAnimationToNewWorkspace(mToState, builder, maxAccuracy); + } if (totalShift == 0) { totalShift = Math.signum(mFromState.ordinal - mToState.ordinal) diff --git a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java index 7b2487ada8..e73b2197fb 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java @@ -34,7 +34,7 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.launcher3.util.TouchController; import com.android.launcher3.views.BaseDragLayer; -import com.android.quickstep.PendingAnimation; +import com.android.launcher3.util.PendingAnimation; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; diff --git a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java index 3cae3718f3..c1590f63de 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java +++ b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java @@ -16,6 +16,7 @@ package com.android.launcher3.uioverrides; +import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.Utilities.getPrefs; import static com.android.quickstep.OverviewInteractionState.KEY_SWIPE_UP_ENABLED; @@ -25,7 +26,9 @@ import android.content.Context; import android.content.SharedPreferences; import com.android.launcher3.AbstractFloatingView; +import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; +import com.android.launcher3.LauncherState; import com.android.launcher3.LauncherStateManager.StateHandler; import com.android.launcher3.util.TouchController; import com.android.quickstep.OverviewInteractionState; @@ -89,11 +92,15 @@ public class UiFactory { } public static void onLauncherStateOrResumeChanged(Launcher launcher) { + LauncherState state = launcher.getStateManager().getState(); + DeviceProfile profile = launcher.getDeviceProfile(); WindowManagerWrapper.getInstance().setShelfHeight( - launcher.getStateManager().getState() != ALL_APPS && - launcher.isUserActive() && - !launcher.getDeviceProfile().isVerticalBarLayout(), - launcher.getDeviceProfile().hotseatBarSizePx); + state != ALL_APPS && launcher.isUserActive() && !profile.isVerticalBarLayout(), + profile.hotseatBarSizePx); + + if (state == NORMAL) { + launcher.getOverviewPanel().setSwipeDownShouldLaunchApp(false); + } } public static void onTrimMemory(Context context, int level) { diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java index 33f13100ce..611f7e0156 100644 --- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -762,6 +762,8 @@ public class WindowTransformSwipeHandler { // Animate the first icon. mRecentsView.setFirstTaskIconScaledDown(false /* isScaledDown */, true /* animate */); + mRecentsView.setSwipeDownShouldLaunchApp(true); + reset(); } diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 50a32e64bc..e7f69b7b38 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -60,7 +60,7 @@ import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.PropertyListBuilder; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.util.Themes; -import com.android.quickstep.PendingAnimation; +import com.android.launcher3.util.PendingAnimation; import com.android.quickstep.QuickScrubController; import com.android.quickstep.RecentsAnimationInterpolator; import com.android.quickstep.RecentsAnimationInterpolator.TaskWindowBounds; @@ -139,6 +139,7 @@ public abstract class RecentsView private boolean mOverviewStateEnabled; private boolean mTaskStackListenerRegistered; private Runnable mNextPageSwitchRunnable; + private boolean mSwipeDownShouldLaunchApp; private PendingAnimation mPendingAnimation; @@ -275,6 +276,9 @@ public abstract class RecentsView mNextPageSwitchRunnable.run(); mNextPageSwitchRunnable = null; } + if (getNextPage() > 0) { + setSwipeDownShouldLaunchApp(true); + } } @Override @@ -601,6 +605,14 @@ public abstract class RecentsView } } + public void setSwipeDownShouldLaunchApp(boolean swipeDownShouldLaunchApp) { + mSwipeDownShouldLaunchApp = swipeDownShouldLaunchApp; + } + + public boolean shouldSwipeDownLaunchApp() { + return mSwipeDownShouldLaunchApp; + } + public interface PageCallbacks { /** diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java index 21f9d5acaa..fdb6f482ad 100644 --- a/src/com/android/launcher3/LauncherState.java +++ b/src/com/android/launcher3/LauncherState.java @@ -18,7 +18,6 @@ package com.android.launcher3; import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_AUTO; import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS; import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED; - import static com.android.launcher3.anim.Interpolators.ACCEL_2; import static com.android.launcher3.states.RotationHelper.REQUEST_NONE; diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java index 4e905fa50a..9726704ddb 100644 --- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java +++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java @@ -30,6 +30,7 @@ import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.launcher3.util.TouchController; +import com.android.launcher3.util.PendingAnimation; /** * TouchController for handling state changes @@ -53,6 +54,7 @@ public abstract class AbstractStateChangeTouchController extends AnimatorListene protected LauncherState mFromState; protected LauncherState mToState; protected AnimatorPlaybackController mCurrentAnimation; + protected PendingAnimation mPendingAnimation; private float mStartProgress; // Ratio of transition process [0, 1] to drag displacement (px) @@ -254,7 +256,16 @@ public abstract class AbstractStateChangeTouchController extends AnimatorListene mLauncher.getWorkspace().getCurrentPage()); } clearState(); - mLauncher.getStateManager().goToState(targetState, false /* animated */); + boolean shouldGoToTargetState = true; + if (mPendingAnimation != null) { + boolean reachedTarget = mToState == targetState; + mPendingAnimation.finish(reachedTarget); + mPendingAnimation = null; + shouldGoToTargetState = !reachedTarget; + } + if (shouldGoToTargetState) { + mLauncher.getStateManager().goToState(targetState, false /* animated */); + } } protected void clearState() { diff --git a/quickstep/src/com/android/quickstep/PendingAnimation.java b/src/com/android/launcher3/util/PendingAnimation.java similarity index 97% rename from quickstep/src/com/android/quickstep/PendingAnimation.java rename to src/com/android/launcher3/util/PendingAnimation.java index d22ef61053..4116d56e1d 100644 --- a/quickstep/src/com/android/quickstep/PendingAnimation.java +++ b/src/com/android/launcher3/util/PendingAnimation.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.quickstep; +package com.android.launcher3.util; import android.animation.AnimatorSet; import android.annotation.TargetApi;