Peek overview on motion pause, then animate fully on touch up
Add AnimationComponents.ATOMIC_OVERVIEW_PEEK_COMPONENT, and rename
previous ATOMIC_COMPONENT to ATOMIC_OVERVIEW_SCALE_COMPONENT.
When SWIPE_HOME is enabled:
- Overview lives to the left of Workspace, which is encoded in
LauncherState.NORMAL.getOverviewScaleAndTranslation().
- Create atomic animation based on ATOMIC_OVERVIEW_PEEK_COMPONENT
and OVERVIEW_PEEK state when swiping and holding from home screen.
Bug: 111926330
Change-Id: Iab6dbef7238dae15b3036d4b2a026b781eee6b4b
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index b6e00cc..a3d5994 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -18,10 +18,10 @@
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.TestProtocol.ALL_APPS_STATE_ORDINAL;
import static com.android.launcher3.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
import static com.android.launcher3.TestProtocol.NORMAL_STATE_ORDINAL;
+import static com.android.launcher3.TestProtocol.OVERVIEW_PEEK_STATE_ORDINAL;
import static com.android.launcher3.TestProtocol.OVERVIEW_STATE_ORDINAL;
import static com.android.launcher3.TestProtocol.SPRING_LOADED_STATE_ORDINAL;
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
@@ -29,9 +29,9 @@
import android.view.animation.Interpolator;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.states.SpringLoadedState;
import com.android.launcher3.uioverrides.AllAppsState;
-import com.android.launcher3.uioverrides.BackgroundAppState;
import com.android.launcher3.uioverrides.OverviewState;
import com.android.launcher3.uioverrides.UiFactory;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
@@ -92,10 +92,13 @@
*/
public static final LauncherState SPRING_LOADED = new SpringLoadedState(
SPRING_LOADED_STATE_ORDINAL);
- public static final LauncherState OVERVIEW = new OverviewState(OVERVIEW_STATE_ORDINAL);
public static final LauncherState ALL_APPS = new AllAppsState(ALL_APPS_STATE_ORDINAL);
- public static final LauncherState BACKGROUND_APP = new BackgroundAppState(
- BACKGROUND_APP_STATE_ORDINAL);
+
+ public static final LauncherState OVERVIEW = new OverviewState(OVERVIEW_STATE_ORDINAL);
+ public static final LauncherState OVERVIEW_PEEK =
+ OverviewState.newPeekState(OVERVIEW_PEEK_STATE_ORDINAL);
+ public static final LauncherState BACKGROUND_APP =
+ OverviewState.newBackgroundState(BACKGROUND_APP_STATE_ORDINAL);
public final int ordinal;
@@ -193,6 +196,11 @@
}
public ScaleAndTranslation getOverviewScaleAndTranslation(Launcher launcher) {
+ if (FeatureFlags.SWIPE_HOME.get()) {
+ float offscreenTranslationX = launcher.getDragLayer().getWidth()
+ - launcher.getOverviewPanel().getPaddingStart();
+ return new ScaleAndTranslation(1f, offscreenTranslationX, 0f);
+ }
return new ScaleAndTranslation(1.1f, 0f, 0f);
}
diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java
index 97c8f51..19c896f 100644
--- a/src/com/android/launcher3/LauncherStateManager.java
+++ b/src/com/android/launcher3/LauncherStateManager.java
@@ -18,14 +18,20 @@
import static android.view.View.VISIBLE;
import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.LauncherState.OVERVIEW;
+import static com.android.launcher3.LauncherState.OVERVIEW_PEEK;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_FADE;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCALE;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATE;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_FADE;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_SCALE;
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7;
+import static com.android.launcher3.anim.Interpolators.INSTANT;
+import static com.android.launcher3.anim.Interpolators.NEVER;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
+import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_7;
import static com.android.launcher3.anim.Interpolators.clampToProgress;
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
@@ -96,17 +102,21 @@
// We separate the state animations into "atomic" and "non-atomic" components. The atomic
// components may be run atomically - that is, all at once, instead of user-controlled. However,
// atomic components are not restricted to this purpose; they can be user-controlled alongside
- // non atomic components as well.
+ // non atomic components as well. Note that each gesture model has exactly one atomic component,
+ // ATOMIC_OVERVIEW_SCALE_COMPONENT *or* ATOMIC_OVERVIEW_PEEK_COMPONENT.
@IntDef(flag = true, value = {
NON_ATOMIC_COMPONENT,
- ATOMIC_COMPONENT
+ ATOMIC_OVERVIEW_SCALE_COMPONENT,
+ ATOMIC_OVERVIEW_PEEK_COMPONENT,
})
@Retention(RetentionPolicy.SOURCE)
public @interface AnimationComponents {}
public static final int NON_ATOMIC_COMPONENT = 1 << 0;
- public static final int ATOMIC_COMPONENT = 1 << 1;
+ public static final int ATOMIC_OVERVIEW_SCALE_COMPONENT = 1 << 1;
+ public static final int ATOMIC_OVERVIEW_PEEK_COMPONENT = 1 << 2;
- public static final int ANIM_ALL = NON_ATOMIC_COMPONENT | ATOMIC_COMPONENT;
+ public static final int ANIM_ALL = NON_ATOMIC_COMPONENT | ATOMIC_OVERVIEW_SCALE_COMPONENT
+ | ATOMIC_OVERVIEW_PEEK_COMPONENT;
private final AnimationConfig mConfig = new AnimationConfig();
private final Handler mUiHandler;
@@ -282,18 +292,20 @@
*/
public void prepareForAtomicAnimation(LauncherState fromState, LauncherState toState,
AnimatorSetBuilder builder) {
- if (fromState == NORMAL && toState.overviewUi) {
+ if (fromState == NORMAL && toState == OVERVIEW) {
builder.setInterpolator(ANIM_WORKSPACE_SCALE, OVERSHOOT_1_2);
builder.setInterpolator(ANIM_WORKSPACE_FADE, OVERSHOOT_1_2);
builder.setInterpolator(ANIM_OVERVIEW_SCALE, OVERSHOOT_1_2);
+ builder.setInterpolator(ANIM_OVERVIEW_TRANSLATE, OVERSHOOT_1_7);
builder.setInterpolator(ANIM_OVERVIEW_FADE, OVERSHOOT_1_2);
// Start from a higher overview scale, but only if we're invisible so we don't jump.
UiFactory.prepareToShowOverview(mLauncher);
- } else if (fromState.overviewUi && toState == NORMAL) {
+ } else if (fromState == OVERVIEW && toState == NORMAL) {
builder.setInterpolator(ANIM_WORKSPACE_SCALE, DEACCEL);
builder.setInterpolator(ANIM_WORKSPACE_FADE, ACCEL);
builder.setInterpolator(ANIM_OVERVIEW_SCALE, clampToProgress(ACCEL, 0, 0.9f));
+ builder.setInterpolator(ANIM_OVERVIEW_TRANSLATE, ACCEL);
builder.setInterpolator(ANIM_OVERVIEW_FADE, DEACCEL_1_7);
Workspace workspace = mLauncher.getWorkspace();
@@ -311,9 +323,25 @@
workspace.getHotseat().setScaleX(0.92f);
workspace.getHotseat().setScaleY(0.92f);
}
+ } else if (fromState == NORMAL && toState == OVERVIEW_PEEK) {
+ builder.setInterpolator(ANIM_OVERVIEW_FADE, INSTANT);
+ } else if (fromState == OVERVIEW_PEEK && toState == NORMAL) {
+ builder.setInterpolator(ANIM_OVERVIEW_FADE, NEVER);
}
}
+ public AnimatorSet createAtomicAnimation(LauncherState fromState, LauncherState toState,
+ AnimatorSetBuilder builder, @AnimationComponents int atomicComponent, long duration) {
+ prepareForAtomicAnimation(fromState, toState, builder);
+ AnimationConfig config = new AnimationConfig();
+ config.animComponents = atomicComponent;
+ config.duration = duration;
+ for (StateHandler handler : mLauncher.getStateManager().getStateHandlers()) {
+ handler.setStateWithAnimation(toState, builder, config);
+ }
+ return builder.build();
+ }
+
/**
* Creates a {@link AnimatorPlaybackController} that can be used for a controlled
* state transition. The UI is force-set to fromState before creating the controller.
@@ -593,8 +621,12 @@
mCurrentAnimation.addListener(this);
}
- public boolean playAtomicComponent() {
- return (animComponents & ATOMIC_COMPONENT) != 0;
+ public boolean playAtomicOverviewScaleComponent() {
+ return (animComponents & ATOMIC_OVERVIEW_SCALE_COMPONENT) != 0;
+ }
+
+ public boolean playAtomicOverviewPeekComponent() {
+ return (animComponents & ATOMIC_OVERVIEW_PEEK_COMPONENT) != 0;
}
public boolean playNonAtomicComponent() {
diff --git a/src/com/android/launcher3/TestProtocol.java b/src/com/android/launcher3/TestProtocol.java
index 4eb3627..8b7279c 100644
--- a/src/com/android/launcher3/TestProtocol.java
+++ b/src/com/android/launcher3/TestProtocol.java
@@ -28,8 +28,9 @@
public static final int NORMAL_STATE_ORDINAL = 0;
public static final int SPRING_LOADED_STATE_ORDINAL = 1;
public static final int OVERVIEW_STATE_ORDINAL = 2;
- public static final int ALL_APPS_STATE_ORDINAL = 3;
- public static final int BACKGROUND_APP_STATE_ORDINAL = 4;
+ public static final int OVERVIEW_PEEK_STATE_ORDINAL = 3;
+ public static final int ALL_APPS_STATE_ORDINAL = 4;
+ public static final int BACKGROUND_APP_STATE_ORDINAL = 5;
public static final String TEST_INFO_RESPONSE_FIELD = "response";
public static final String REQUEST_HOME_TO_OVERVIEW_SWIPE_HEIGHT =
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index bed61a1..21fdd3d 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -86,7 +86,7 @@
int elements = state.getVisibleElements(mLauncher);
Interpolator fadeInterpolator = builder.getInterpolator(ANIM_WORKSPACE_FADE,
pageAlphaProvider.interpolator);
- boolean playAtomicComponent = config.playAtomicComponent();
+ boolean playAtomicComponent = config.playAtomicOverviewScaleComponent();
Hotseat hotseat = mWorkspace.getHotseat();
if (playAtomicComponent) {
Interpolator scaleInterpolator = builder.getInterpolator(ANIM_WORKSPACE_SCALE, ZOOM_OUT);
@@ -147,7 +147,7 @@
propertySetter.setInt(cl.getScrimBackground(),
DRAWABLE_ALPHA, drawableAlpha, ZOOM_OUT);
}
- if (config.playAtomicComponent()) {
+ if (config.playAtomicOverviewScaleComponent()) {
Interpolator fadeInterpolator = builder.getInterpolator(ANIM_WORKSPACE_FADE,
pageAlphaProvider.interpolator);
propertySetter.setFloat(cl.getShortcutsAndWidgets(), View.ALPHA,
diff --git a/src/com/android/launcher3/anim/Interpolators.java b/src/com/android/launcher3/anim/Interpolators.java
index 675e26d..217b6db 100644
--- a/src/com/android/launcher3/anim/Interpolators.java
+++ b/src/com/android/launcher3/anim/Interpolators.java
@@ -57,6 +57,9 @@
public static final Interpolator EXAGGERATED_EASE;
+ public static final Interpolator INSTANT = t -> 1;
+ public static final Interpolator NEVER = t -> 0;
+
private static final int MIN_SETTLE_DURATION = 200;
private static final float OVERSHOOT_FACTOR = 0.9f;
@@ -69,6 +72,7 @@
}
public static final Interpolator OVERSHOOT_1_2 = new OvershootInterpolator(1.2f);
+ public static final Interpolator OVERSHOOT_1_7 = new OvershootInterpolator(1.7f);
public static final Interpolator TOUCH_RESPONSE_INTERPOLATOR =
new PathInterpolator(0.3f, 0f, 0.1f, 1f);
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index c125c10..86deb43 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -20,7 +20,7 @@
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherStateManager.ANIM_ALL;
-import static com.android.launcher3.LauncherStateManager.ATOMIC_COMPONENT;
+import static com.android.launcher3.LauncherStateManager.ATOMIC_OVERVIEW_SCALE_COMPONENT;
import static com.android.launcher3.LauncherStateManager.NON_ATOMIC_COMPONENT;
import static com.android.launcher3.Utilities.SINGLE_FRAME_MS;
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
@@ -38,9 +38,6 @@
import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager.AnimationComponents;
-import com.android.launcher3.LauncherStateManager.AnimationConfig;
-import com.android.launcher3.LauncherStateManager.StateHandler;
-import com.android.launcher3.TestProtocol;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
@@ -68,7 +65,7 @@
* Play an atomic recents animation when the progress from NORMAL to OVERVIEW reaches this.
*/
public static final float ATOMIC_OVERVIEW_ANIM_THRESHOLD = 0.5f;
- protected static final long ATOMIC_DURATION = 200;
+ protected final long ATOMIC_DURATION = getAtomicDuration();
protected final Launcher mLauncher;
protected final SwipeDetector mDetector;
@@ -110,6 +107,10 @@
mDetector = new SwipeDetector(l, this, dir);
}
+ protected long getAtomicDuration() {
+ return 200;
+ }
+
protected abstract boolean canInterceptTouch(MotionEvent ev);
@Override
@@ -214,7 +215,7 @@
}
if (mAtomicComponentsController != null) {
- animComponents &= ~ATOMIC_COMPONENT;
+ animComponents &= ~ATOMIC_OVERVIEW_SCALE_COMPONENT;
}
mProgressMultiplier = initCurrentAnimation(animComponents);
mCurrentAnimation.dispatchOnStart();
@@ -297,7 +298,7 @@
* When going between normal and overview states, see if we passed the overview threshold and
* play the appropriate atomic animation if so.
*/
- protected void maybeUpdateAtomicAnim(LauncherState fromState, LauncherState toState,
+ private void maybeUpdateAtomicAnim(LauncherState fromState, LauncherState toState,
float progress) {
if (!goingBetweenNormalAndOverview(fromState, toState)) {
return;
@@ -347,14 +348,8 @@
private AnimatorSet createAtomicAnimForState(LauncherState fromState, LauncherState targetState,
long duration) {
AnimatorSetBuilder builder = getAnimatorSetBuilderForStates(fromState, targetState);
- mLauncher.getStateManager().prepareForAtomicAnimation(fromState, targetState, builder);
- AnimationConfig config = new AnimationConfig();
- config.animComponents = ATOMIC_COMPONENT;
- config.duration = duration;
- for (StateHandler handler : mLauncher.getStateManager().getStateHandlers()) {
- handler.setStateWithAnimation(targetState, builder, config);
- }
- return builder.build();
+ return mLauncher.getStateManager().createAtomicAnimation(fromState, targetState, builder,
+ ATOMIC_OVERVIEW_SCALE_COMPONENT, duration);
}
protected AnimatorSetBuilder getAnimatorSetBuilderForStates(LauncherState fromState,
@@ -434,11 +429,7 @@
mLauncher.getAppsView().addSpringFromFlingUpdateListener(anim, velocity);
}
anim.start();
- settleAtomicAnimation(endProgress, anim.getDuration());
- }
-
- protected void settleAtomicAnimation(float endProgress, long duration) {
- mAtomicAnimAutoPlayInfo = new AutoPlayAtomicAnimationInfo(endProgress, duration);
+ mAtomicAnimAutoPlayInfo = new AutoPlayAtomicAnimationInfo(endProgress, anim.getDuration());
maybeAutoPlayAtomicComponentsAnim();
}