Some improvements to home to overview transition for 0 button mode

- Peek in overview further, and with more overshoot
- Fade out and scale down workspace faster while swiping up
- Scale and translate workspace slower when letting go to enter
  overview (so it doesn't zoom out at warp speed)
- Fade in all apps shelf sooner

Bug: 132455160
Change-Id: Ieafad0ccf9bb587889bc35d536627661db10e358
This commit is contained in:
Tony Wickham 2019-06-18 16:34:37 -07:00 committed by Sunny Goyal
parent 035770e421
commit 59c6901823
14 changed files with 227 additions and 120 deletions

View File

@ -16,11 +16,6 @@
package com.android.launcher3.uioverrides; package com.android.launcher3.uioverrides;
import static android.view.View.VISIBLE;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import android.view.View;
import com.android.launcher3.DeviceProfile; import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher; import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherStateManager.StateHandler; import com.android.launcher3.LauncherStateManager.StateHandler;
@ -43,8 +38,6 @@ import java.util.ArrayList;
public abstract class RecentsUiFactory { public abstract class RecentsUiFactory {
public static final boolean GO_LOW_RAM_RECENTS_ENABLED = true; public static final boolean GO_LOW_RAM_RECENTS_ENABLED = true;
// Scale recents takes before animating in
private static final float RECENTS_PREPARE_SCALE = 1.33f;
public static TouchController[] createTouchControllers(Launcher launcher) { public static TouchController[] createTouchControllers(Launcher launcher) {
ArrayList<TouchController> list = new ArrayList<>(); ArrayList<TouchController> list = new ArrayList<>();
@ -76,18 +69,6 @@ public abstract class RecentsUiFactory {
return new RecentsViewStateController(launcher); return new RecentsViewStateController(launcher);
} }
/**
* Prepare the recents view to animate in.
*
* @param launcher the launcher activity
*/
public static void prepareToShowOverview(Launcher launcher) {
View overview = launcher.getOverviewPanel();
if (overview.getVisibility() != VISIBLE) {
SCALE_PROPERTY.set(overview, RECENTS_PREPARE_SCALE);
}
}
/** /**
* Clean-up logic that occurs when recents is no longer in use/visible. * Clean-up logic that occurs when recents is no longer in use/visible.
* *

View File

@ -16,15 +16,31 @@
package com.android.launcher3.uioverrides.states; package com.android.launcher3.uioverrides.states;
import static android.view.View.VISIBLE;
import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS; import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
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_X;
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.AnimatorSetBuilder.ANIM_WORKSPACE_TRANSLATE;
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL_2; import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
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.states.RotationHelper.REQUEST_ROTATE; import static com.android.launcher3.states.RotationHelper.REQUEST_ROTATE;
import android.view.View;
import com.android.launcher3.DeviceProfile; import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher; import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState; import com.android.launcher3.LauncherState;
import com.android.launcher3.R; import com.android.launcher3.R;
import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.views.IconRecentsView; import com.android.quickstep.views.IconRecentsView;
/** /**
@ -32,6 +48,9 @@ import com.android.quickstep.views.IconRecentsView;
*/ */
public class OverviewState extends LauncherState { public class OverviewState extends LauncherState {
// Scale recents takes before animating in
private static final float RECENTS_PREPARE_SCALE = 1.33f;
private static final int STATE_FLAGS = FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED private static final int STATE_FLAGS = FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED
| FLAG_DISABLE_RESTORE | FLAG_OVERVIEW_UI | FLAG_DISABLE_ACCESSIBILITY; | FLAG_DISABLE_RESTORE | FLAG_OVERVIEW_UI | FLAG_DISABLE_ACCESSIBILITY;
@ -103,6 +122,27 @@ public class OverviewState extends LauncherState {
return dp.allAppsCellHeightPx - dp.allAppsIconTextSizePx; return dp.allAppsCellHeightPx - dp.allAppsIconTextSizePx;
} }
@Override
public void prepareForAtomicAnimation(Launcher launcher, LauncherState fromState,
AnimatorSetBuilder builder) {
if (fromState == NORMAL && this == OVERVIEW) {
if (SysUINavigationMode.getMode(launcher) == SysUINavigationMode.Mode.NO_BUTTON) {
builder.setInterpolator(ANIM_WORKSPACE_SCALE, ACCEL);
builder.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCEL);
} else {
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_X, OVERSHOOT_1_7);
builder.setInterpolator(ANIM_OVERVIEW_FADE, OVERSHOOT_1_2);
View overview = launcher.getOverviewPanel();
if (overview.getVisibility() != VISIBLE) {
SCALE_PROPERTY.set(overview, RECENTS_PREPARE_SCALE);
}
}
}
public static OverviewState newBackgroundState(int id) { public static OverviewState newBackgroundState(int id) {
return new OverviewState(id); return new OverviewState(id);

View File

@ -16,8 +16,6 @@
package com.android.launcher3.uioverrides; package com.android.launcher3.uioverrides;
import static android.view.View.VISIBLE;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON; import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
@ -62,9 +60,6 @@ public abstract class RecentsUiFactory {
private static final AsyncCommand SET_SHELF_HEIGHT_CMD = (visible, height) -> private static final AsyncCommand SET_SHELF_HEIGHT_CMD = (visible, height) ->
WindowManagerWrapper.getInstance().setShelfHeight(visible != 0, height); WindowManagerWrapper.getInstance().setShelfHeight(visible != 0, height);
// Scale recents takes before animating in
private static final float RECENTS_PREPARE_SCALE = 1.33f;
public static RotationMode ROTATION_LANDSCAPE = new RotationMode(-90) { public static RotationMode ROTATION_LANDSCAPE = new RotationMode(-90) {
@Override @Override
public void mapRect(int left, int top, int right, int bottom, Rect out) { public void mapRect(int left, int top, int right, int bottom, Rect out) {
@ -188,22 +183,6 @@ public abstract class RecentsUiFactory {
return new RecentsViewStateController(launcher); return new RecentsViewStateController(launcher);
} }
/**
* Prepare the recents view to animate in.
*
* @param launcher the launcher activity
*/
public static void prepareToShowOverview(Launcher launcher) {
if (SysUINavigationMode.getMode(launcher) == NO_BUTTON) {
// Overview lives on the side, so doesn't scale in from above.
return;
}
RecentsView overview = launcher.getOverviewPanel();
if (overview.getVisibility() != VISIBLE || overview.getContentAlpha() == 0) {
SCALE_PROPERTY.set(overview, RECENTS_PREPARE_SCALE);
}
}
/** /**
* Recents logic that triggers when launcher state changes or launcher activity stops/resumes. * Recents logic that triggers when launcher state changes or launcher activity stops/resumes.
* *

View File

@ -14,8 +14,15 @@
* limitations under the License. * limitations under the License.
*/ */
package com.android.launcher3.uioverrides.states; package com.android.launcher3.uioverrides.states;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_FADE;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATE_X;
import static com.android.launcher3.anim.Interpolators.INSTANT;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_7;
import com.android.launcher3.Launcher; import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R; import com.android.launcher3.R;
import com.android.launcher3.anim.AnimatorSetBuilder;
public class OverviewPeekState extends OverviewState { public class OverviewPeekState extends OverviewState {
public OverviewPeekState(int id) { public OverviewPeekState(int id) {
@ -29,4 +36,13 @@ public class OverviewPeekState extends OverviewState {
- launcher.getResources().getDimension(R.dimen.overview_peek_distance); - launcher.getResources().getDimension(R.dimen.overview_peek_distance);
return result; return result;
} }
@Override
public void prepareForAtomicAnimation(Launcher launcher, LauncherState fromState,
AnimatorSetBuilder builder) {
if (this == OVERVIEW_PEEK && fromState == NORMAL) {
builder.setInterpolator(ANIM_OVERVIEW_FADE, INSTANT);
builder.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, OVERSHOOT_1_7);
}
}
} }

View File

@ -15,8 +15,20 @@
*/ */
package com.android.launcher3.uioverrides.states; package com.android.launcher3.uioverrides.states;
import static android.view.View.VISIBLE;
import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS; import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
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_X;
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.AnimatorSetBuilder.ANIM_WORKSPACE_TRANSLATE;
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL_2; import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
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.logging.LoggerUtils.newContainerTarget; import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
import static com.android.launcher3.states.RotationHelper.REQUEST_ROTATE; import static com.android.launcher3.states.RotationHelper.REQUEST_ROTATE;
@ -30,8 +42,11 @@ import com.android.launcher3.LauncherState;
import com.android.launcher3.R; import com.android.launcher3.R;
import com.android.launcher3.Workspace; import com.android.launcher3.Workspace;
import com.android.launcher3.allapps.DiscoveryBounce; import com.android.launcher3.allapps.DiscoveryBounce;
import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.uioverrides.UiFactory;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action; import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView; import com.android.quickstep.views.TaskView;
@ -40,6 +55,9 @@ import com.android.quickstep.views.TaskView;
*/ */
public class OverviewState extends LauncherState { public class OverviewState extends LauncherState {
// Scale recents takes before animating in
private static final float RECENTS_PREPARE_SCALE = 1.33f;
protected static final Rect sTempRect = new Rect(); protected static final Rect sTempRect = new Rect();
private static final int STATE_FLAGS = FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED private static final int STATE_FLAGS = FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED
@ -160,6 +178,29 @@ public class OverviewState extends LauncherState {
} }
} }
@Override
public void prepareForAtomicAnimation(Launcher launcher, LauncherState fromState,
AnimatorSetBuilder builder) {
if (fromState == NORMAL && this == OVERVIEW) {
if (SysUINavigationMode.getMode(launcher) == SysUINavigationMode.Mode.NO_BUTTON) {
builder.setInterpolator(ANIM_WORKSPACE_SCALE, ACCEL);
builder.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCEL);
} else {
builder.setInterpolator(ANIM_WORKSPACE_SCALE, OVERSHOOT_1_2);
// Scale up the recents, if it is not coming from the side
RecentsView overview = launcher.getOverviewPanel();
if (overview.getVisibility() != VISIBLE || overview.getContentAlpha() == 0) {
SCALE_PROPERTY.set(overview, RECENTS_PREPARE_SCALE);
}
}
builder.setInterpolator(ANIM_WORKSPACE_FADE, OVERSHOOT_1_2);
builder.setInterpolator(ANIM_OVERVIEW_SCALE, OVERSHOOT_1_2);
builder.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, OVERSHOOT_1_7);
builder.setInterpolator(ANIM_OVERVIEW_FADE, OVERSHOOT_1_2);
}
}
public static OverviewState newBackgroundState(int id) { public static OverviewState newBackgroundState(int id) {
return new BackgroundAppState(id); return new BackgroundAppState(id);
} }

View File

@ -16,11 +16,20 @@
package com.android.launcher3.uioverrides.touchcontrollers; package com.android.launcher3.uioverrides.touchcontrollers;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.OVERVIEW_PEEK; import static com.android.launcher3.LauncherState.OVERVIEW_PEEK;
import static com.android.launcher3.LauncherStateManager.ANIM_ALL; import static com.android.launcher3.LauncherStateManager.ANIM_ALL;
import static com.android.launcher3.LauncherStateManager.ATOMIC_OVERVIEW_PEEK_COMPONENT; import static com.android.launcher3.LauncherStateManager.ATOMIC_OVERVIEW_PEEK_COMPONENT;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_HOTSEAT_SCALE;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_HOTSEAT_TRANSLATE;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS;
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.AnimatorSetBuilder.ANIM_WORKSPACE_TRANSLATE;
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2; import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
@ -38,14 +47,14 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.quickstep.OverviewInteractionState; import com.android.quickstep.OverviewInteractionState;
import com.android.quickstep.util.MotionPauseDetector; import com.android.quickstep.util.MotionPauseDetector;
import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.QuickStepContract;
/** /**
* Touch controller which handles swipe and hold to go to Overview * Touch controller which handles swipe and hold to go to Overview
*/ */
public class FlingAndHoldTouchController extends PortraitStatesTouchController { public class FlingAndHoldTouchController extends PortraitStatesTouchController {
private static final long PEEK_ANIM_DURATION = 100; private static final long PEEK_IN_ANIM_DURATION = 240;
private static final long PEEK_OUT_ANIM_DURATION = 100;
private static final float MAX_DISPLACEMENT_PERCENT = 0.75f; private static final float MAX_DISPLACEMENT_PERCENT = 0.75f;
private final MotionPauseDetector mMotionPauseDetector; private final MotionPauseDetector mMotionPauseDetector;
@ -81,9 +90,9 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
} }
LauncherState fromState = isPaused ? NORMAL : OVERVIEW_PEEK; LauncherState fromState = isPaused ? NORMAL : OVERVIEW_PEEK;
LauncherState toState = isPaused ? OVERVIEW_PEEK : NORMAL; LauncherState toState = isPaused ? OVERVIEW_PEEK : NORMAL;
long peekDuration = isPaused ? PEEK_IN_ANIM_DURATION : PEEK_OUT_ANIM_DURATION;
mPeekAnim = mLauncher.getStateManager().createAtomicAnimation(fromState, toState, mPeekAnim = mLauncher.getStateManager().createAtomicAnimation(fromState, toState,
new AnimatorSetBuilder(), ATOMIC_OVERVIEW_PEEK_COMPONENT, new AnimatorSetBuilder(), ATOMIC_OVERVIEW_PEEK_COMPONENT, peekDuration);
PEEK_ANIM_DURATION);
mPeekAnim.addListener(new AnimatorListenerAdapter() { mPeekAnim.addListener(new AnimatorListenerAdapter() {
@Override @Override
public void onAnimationEnd(Animator animation) { public void onAnimationEnd(Animator animation) {
@ -106,6 +115,21 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
return mStartState == NORMAL && (stateFlags & SYSUI_STATE_OVERVIEW_DISABLED) == 0; return mStartState == NORMAL && (stateFlags & SYSUI_STATE_OVERVIEW_DISABLED) == 0;
} }
@Override
protected AnimatorSetBuilder getAnimatorSetBuilderForStates(LauncherState fromState,
LauncherState toState) {
if (fromState == NORMAL && toState == ALL_APPS) {
AnimatorSetBuilder builder = new AnimatorSetBuilder();
// Get workspace out of the way quickly, to prepare for potential pause.
builder.setInterpolator(ANIM_WORKSPACE_SCALE, DEACCEL_3);
builder.setInterpolator(ANIM_WORKSPACE_TRANSLATE, DEACCEL_3);
builder.setInterpolator(ANIM_WORKSPACE_FADE, DEACCEL_3);
return builder;
}
return super.getAnimatorSetBuilderForStates(fromState, toState);
}
@Override @Override
public boolean onDrag(float displacement, MotionEvent event) { public boolean onDrag(float displacement, MotionEvent event) {
float upDisplacement = -displacement; float upDisplacement = -displacement;
@ -123,8 +147,11 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
} }
AnimatorSetBuilder builder = new AnimatorSetBuilder(); AnimatorSetBuilder builder = new AnimatorSetBuilder();
builder.setInterpolator(AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS, OVERSHOOT_1_2); builder.setInterpolator(ANIM_VERTICAL_PROGRESS, OVERSHOOT_1_2);
builder.setInterpolator(AnimatorSetBuilder.ANIM_WORKSPACE_TRANSLATE, OVERSHOOT_1_2); if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
builder.setInterpolator(ANIM_HOTSEAT_SCALE, OVERSHOOT_1_2);
builder.setInterpolator(ANIM_HOTSEAT_TRANSLATE, OVERSHOOT_1_2);
}
AnimatorSet overviewAnim = mLauncher.getStateManager().createAtomicAnimation( AnimatorSet overviewAnim = mLauncher.getStateManager().createAtomicAnimation(
NORMAL, OVERVIEW, builder, ANIM_ALL, ATOMIC_DURATION); NORMAL, OVERVIEW, builder, ANIM_ALL, ATOMIC_DURATION);
overviewAnim.addListener(new AnimatorListenerAdapter() { overviewAnim.addListener(new AnimatorListenerAdapter() {

View File

@ -24,7 +24,7 @@
<dimen name="recents_page_spacing">10dp</dimen> <dimen name="recents_page_spacing">10dp</dimen>
<dimen name="recents_clear_all_deadzone_vertical_margin">70dp</dimen> <dimen name="recents_clear_all_deadzone_vertical_margin">70dp</dimen>
<dimen name="overview_peek_distance">32dp</dimen> <dimen name="overview_peek_distance">96dp</dimen>
<!-- The speed in dp/s at which the user needs to be scrolling in recents such that we start <!-- The speed in dp/s at which the user needs to be scrolling in recents such that we start
loading full resolution screenshots. --> loading full resolution screenshots. -->

View File

@ -23,6 +23,7 @@ import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState; import com.android.launcher3.LauncherState;
import com.android.launcher3.allapps.AllAppsContainerView; import com.android.launcher3.allapps.AllAppsContainerView;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.quickstep.SysUINavigationMode;
/** /**
* Definition for AllApps state * Definition for AllApps state
@ -63,7 +64,13 @@ public class AllAppsState extends LauncherState {
public ScaleAndTranslation getWorkspaceScaleAndTranslation(Launcher launcher) { public ScaleAndTranslation getWorkspaceScaleAndTranslation(Launcher launcher) {
ScaleAndTranslation scaleAndTranslation = LauncherState.OVERVIEW ScaleAndTranslation scaleAndTranslation = LauncherState.OVERVIEW
.getWorkspaceScaleAndTranslation(launcher); .getWorkspaceScaleAndTranslation(launcher);
if (SysUINavigationMode.getMode(launcher) == SysUINavigationMode.Mode.NO_BUTTON) {
float normalScale = 1;
// Scale down halfway to where we'd be in overview, to prepare for a potential pause.
scaleAndTranslation.scale = (scaleAndTranslation.scale + normalScale) / 2;
} else {
scaleAndTranslation.scale = 1; scaleAndTranslation.scale = 1;
}
return scaleAndTranslation; return scaleAndTranslation;
} }

View File

@ -18,6 +18,7 @@ package com.android.quickstep.views;
import static com.android.launcher3.LauncherState.BACKGROUND_APP; import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.anim.Interpolators.ACCEL; import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound; import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
@ -29,6 +30,7 @@ import android.graphics.Path;
import android.graphics.Path.Direction; import android.graphics.Path.Direction;
import android.graphics.Path.Op; import android.graphics.Path.Op;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.animation.Interpolator;
import com.android.launcher3.DeviceProfile; import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R; import com.android.launcher3.R;
@ -69,6 +71,9 @@ public class ShelfScrimView extends ScrimView implements NavigationModeChangeLis
private int mMidAlpha; private int mMidAlpha;
private float mMidProgress; private float mMidProgress;
private Interpolator mBeforeMidProgressColorInterpolator = ACCEL;
private Interpolator mAfterMidProgressColorInterpolator = ACCEL;
private float mShiftRange; private float mShiftRange;
private final float mShelfOffset; private final float mShelfOffset;
@ -120,6 +125,15 @@ public class ShelfScrimView extends ScrimView implements NavigationModeChangeLis
@Override @Override
public void onNavigationModeChanged(Mode newMode) { public void onNavigationModeChanged(Mode newMode) {
mSysUINavigationMode = newMode; mSysUINavigationMode = newMode;
// Note that these interpolators are inverted because progress goes 1 to 0.
if (mSysUINavigationMode == Mode.NO_BUTTON) {
// Show the shelf more quickly before reaching overview progress.
mBeforeMidProgressColorInterpolator = ACCEL_2;
mAfterMidProgressColorInterpolator = ACCEL;
} else {
mBeforeMidProgressColorInterpolator = ACCEL;
mAfterMidProgressColorInterpolator = Interpolators.clampToProgress(ACCEL, 0.5f, 1f);
}
} }
@Override @Override
@ -171,7 +185,7 @@ public class ShelfScrimView extends ScrimView implements NavigationModeChangeLis
mRemainingScreenColor = 0; mRemainingScreenColor = 0;
int alpha = Math.round(Utilities.mapToRange( int alpha = Math.round(Utilities.mapToRange(
mProgress, mMidProgress, 1, mMidAlpha, 0, ACCEL)); mProgress, mMidProgress, 1, mMidAlpha, 0, mBeforeMidProgressColorInterpolator));
mShelfColor = setColorAlphaBound(mEndScrim, alpha); mShelfColor = setColorAlphaBound(mEndScrim, alpha);
} else { } else {
mDragHandleOffset += mShiftRange * (mMidProgress - mProgress); mDragHandleOffset += mShiftRange * (mMidProgress - mProgress);
@ -179,7 +193,7 @@ public class ShelfScrimView extends ScrimView implements NavigationModeChangeLis
// Note that these ranges and interpolators are inverted because progress goes 1 to 0. // Note that these ranges and interpolators are inverted because progress goes 1 to 0.
int alpha = Math.round( int alpha = Math.round(
Utilities.mapToRange(mProgress, (float) 0, mMidProgress, (float) mEndAlpha, Utilities.mapToRange(mProgress, (float) 0, mMidProgress, (float) mEndAlpha,
(float) mMidAlpha, Interpolators.clampToProgress(ACCEL, 0.5f, 1f))); (float) mMidAlpha, mAfterMidProgressColorInterpolator));
mShelfColor = setColorAlphaBound(mEndScrim, alpha); mShelfColor = setColorAlphaBound(mEndScrim, alpha);
int remainingScrimAlpha = Math.round( int remainingScrimAlpha = Math.round(

View File

@ -17,7 +17,18 @@ package com.android.launcher3;
import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_AUTO; import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_AUTO;
import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS; import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
import static android.view.View.VISIBLE;
import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED; import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
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_X;
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.clampToProgress;
import static com.android.launcher3.testing.TestProtocol.ALL_APPS_STATE_ORDINAL; import static com.android.launcher3.testing.TestProtocol.ALL_APPS_STATE_ORDINAL;
import static com.android.launcher3.testing.TestProtocol.BACKGROUND_APP_STATE_ORDINAL; import static com.android.launcher3.testing.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
import static com.android.launcher3.testing.TestProtocol.NORMAL_STATE_ORDINAL; import static com.android.launcher3.testing.TestProtocol.NORMAL_STATE_ORDINAL;
@ -30,11 +41,11 @@ import static com.android.launcher3.states.RotationHelper.REQUEST_NONE;
import android.view.animation.Interpolator; import android.view.animation.Interpolator;
import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.states.SpringLoadedState; import com.android.launcher3.states.SpringLoadedState;
import com.android.launcher3.uioverrides.UiFactory; import com.android.launcher3.uioverrides.UiFactory;
import com.android.launcher3.uioverrides.states.AllAppsState; import com.android.launcher3.uioverrides.states.AllAppsState;
import com.android.launcher3.uioverrides.states.OverviewState; import com.android.launcher3.uioverrides.states.OverviewState;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import java.util.Arrays; import java.util.Arrays;
@ -272,6 +283,46 @@ public class LauncherState {
} }
} }
/**
* Prepares for a non-user controlled animation from fromState to this state. Preparations
* include:
* - Setting interpolators for various animations included in the state transition.
* - Setting some start values (e.g. scale) for views that are hidden but about to be shown.
*/
public void prepareForAtomicAnimation(Launcher launcher, LauncherState fromState,
AnimatorSetBuilder builder) {
if (this == NORMAL && fromState == OVERVIEW) {
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_X, ACCEL);
builder.setInterpolator(ANIM_OVERVIEW_FADE, DEACCEL_1_7);
Workspace workspace = launcher.getWorkspace();
// Start from a higher workspace scale, but only if we're invisible so we don't jump.
boolean isWorkspaceVisible = workspace.getVisibility() == VISIBLE;
if (isWorkspaceVisible) {
CellLayout currentChild = (CellLayout) workspace.getChildAt(
workspace.getCurrentPage());
isWorkspaceVisible = currentChild.getVisibility() == VISIBLE
&& currentChild.getShortcutsAndWidgets().getAlpha() > 0;
}
if (!isWorkspaceVisible) {
workspace.setScaleX(0.92f);
workspace.setScaleY(0.92f);
}
Hotseat hotseat = launcher.getHotseat();
boolean isHotseatVisible = hotseat.getVisibility() == VISIBLE && hotseat.getAlpha() > 0;
if (!isHotseatVisible) {
hotseat.setScaleX(0.92f);
hotseat.setScaleY(0.92f);
}
} else if (this == NORMAL && fromState == OVERVIEW_PEEK) {
// Keep fully visible until the very end (when overview is offscreen) to make invisible.
builder.setInterpolator(ANIM_OVERVIEW_FADE, t -> t < 1 ? 0 : 1);
}
}
protected static void dispatchWindowStateChanged(Launcher launcher) { protected static void dispatchWindowStateChanged(Launcher launcher) {
launcher.getWindow().getDecorView().sendAccessibilityEvent(TYPE_WINDOW_STATE_CHANGED); launcher.getWindow().getDecorView().sendAccessibilityEvent(TYPE_WINDOW_STATE_CHANGED);
} }

View File

@ -16,23 +16,7 @@
package com.android.launcher3; package com.android.launcher3;
import static android.view.View.VISIBLE;
import static com.android.launcher3.LauncherState.NORMAL; 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_X;
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.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; import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
import android.animation.Animator; import android.animation.Animator;
@ -42,8 +26,6 @@ import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.util.Log; import android.util.Log;
import androidx.annotation.IntDef;
import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.AnimatorSetBuilder; import com.android.launcher3.anim.AnimatorSetBuilder;
@ -58,6 +40,8 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList; import java.util.ArrayList;
import androidx.annotation.IntDef;
/** /**
* TODO: figure out what kind of tests we can write for this * TODO: figure out what kind of tests we can write for this
* *
@ -314,47 +298,7 @@ public class LauncherStateManager {
*/ */
public void prepareForAtomicAnimation(LauncherState fromState, LauncherState toState, public void prepareForAtomicAnimation(LauncherState fromState, LauncherState toState,
AnimatorSetBuilder builder) { AnimatorSetBuilder builder) {
if (fromState == NORMAL && toState == OVERVIEW) { toState.prepareForAtomicAnimation(mLauncher, fromState, builder);
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_X, 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 == 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_X, ACCEL);
builder.setInterpolator(ANIM_OVERVIEW_FADE, DEACCEL_1_7);
Workspace workspace = mLauncher.getWorkspace();
// Start from a higher workspace scale, but only if we're invisible so we don't jump.
boolean isWorkspaceVisible = workspace.getVisibility() == VISIBLE;
if (isWorkspaceVisible) {
CellLayout currentChild = (CellLayout) workspace.getChildAt(
workspace.getCurrentPage());
isWorkspaceVisible = currentChild.getVisibility() == VISIBLE
&& currentChild.getShortcutsAndWidgets().getAlpha() > 0;
}
if (!isWorkspaceVisible) {
workspace.setScaleX(0.92f);
workspace.setScaleY(0.92f);
}
Hotseat hotseat = workspace.getHotseat();
boolean isHotseatVisible = hotseat.getVisibility() == VISIBLE && hotseat.getAlpha() > 0;
if (!isHotseatVisible) {
hotseat.setScaleX(0.92f);
hotseat.setScaleY(0.92f);
}
} else if (fromState == NORMAL && toState == OVERVIEW_PEEK) {
builder.setInterpolator(ANIM_OVERVIEW_FADE, INSTANT);
} else if (fromState == OVERVIEW_PEEK && toState == NORMAL) {
// Keep fully visible until the very end (when overview is offscreen) to make invisible.
builder.setInterpolator(ANIM_OVERVIEW_FADE, t -> t < 1 ? 0 : 1);
}
} }
public AnimatorSet createAtomicAnimation(LauncherState fromState, LauncherState toState, public AnimatorSet createAtomicAnimation(LauncherState fromState, LauncherState toState,

View File

@ -19,6 +19,8 @@ package com.android.launcher3;
import static com.android.launcher3.LauncherAnimUtils.DRAWABLE_ALPHA; import static com.android.launcher3.LauncherAnimUtils.DRAWABLE_ALPHA;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS; import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_HOTSEAT_SCALE;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_HOTSEAT_TRANSLATE;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_FADE; 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.AnimatorSetBuilder.ANIM_WORKSPACE_SCALE;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_TRANSLATE; import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_TRANSLATE;
@ -104,7 +106,10 @@ public class WorkspaceStateTransitionAnimation {
hotseat.setPivotY(workspacePivot[1]); hotseat.setPivotY(workspacePivot[1]);
} }
float hotseatScale = hotseatScaleAndTranslation.scale; float hotseatScale = hotseatScaleAndTranslation.scale;
propertySetter.setFloat(hotseat, SCALE_PROPERTY, hotseatScale, scaleInterpolator); Interpolator hotseatScaleInterpolator = builder.getInterpolator(ANIM_HOTSEAT_SCALE,
scaleInterpolator);
propertySetter.setFloat(hotseat, SCALE_PROPERTY, hotseatScale,
hotseatScaleInterpolator);
float hotseatIconsAlpha = (elements & HOTSEAT_ICONS) != 0 ? 1 : 0; float hotseatIconsAlpha = (elements & HOTSEAT_ICONS) != 0 ? 1 : 0;
propertySetter.setViewAlpha(hotseat, hotseatIconsAlpha, fadeInterpolator); propertySetter.setViewAlpha(hotseat, hotseatIconsAlpha, fadeInterpolator);
@ -125,10 +130,12 @@ public class WorkspaceStateTransitionAnimation {
propertySetter.setFloat(mWorkspace, View.TRANSLATION_Y, propertySetter.setFloat(mWorkspace, View.TRANSLATION_Y,
scaleAndTranslation.translationY, translationInterpolator); scaleAndTranslation.translationY, translationInterpolator);
Interpolator hotseatTranslationInterpolator = builder.getInterpolator(
ANIM_HOTSEAT_TRANSLATE, translationInterpolator);
propertySetter.setFloat(hotseat, View.TRANSLATION_Y, propertySetter.setFloat(hotseat, View.TRANSLATION_Y,
hotseatScaleAndTranslation.translationY, translationInterpolator); hotseatScaleAndTranslation.translationY, hotseatTranslationInterpolator);
propertySetter.setFloat(mWorkspace.getPageIndicator(), View.TRANSLATION_Y, propertySetter.setFloat(mWorkspace.getPageIndicator(), View.TRANSLATION_Y,
hotseatScaleAndTranslation.translationY, translationInterpolator); hotseatScaleAndTranslation.translationY, hotseatTranslationInterpolator);
setScrim(propertySetter, state); setScrim(propertySetter, state);
} }

View File

@ -32,11 +32,13 @@ public class AnimatorSetBuilder {
public static final int ANIM_WORKSPACE_SCALE = 1; public static final int ANIM_WORKSPACE_SCALE = 1;
public static final int ANIM_WORKSPACE_TRANSLATE = 2; public static final int ANIM_WORKSPACE_TRANSLATE = 2;
public static final int ANIM_WORKSPACE_FADE = 3; public static final int ANIM_WORKSPACE_FADE = 3;
public static final int ANIM_OVERVIEW_SCALE = 4; public static final int ANIM_HOTSEAT_SCALE = 4;
public static final int ANIM_OVERVIEW_TRANSLATE_X = 5; public static final int ANIM_HOTSEAT_TRANSLATE = 5;
public static final int ANIM_OVERVIEW_TRANSLATE_Y = 6; public static final int ANIM_OVERVIEW_SCALE = 6;
public static final int ANIM_OVERVIEW_FADE = 7; public static final int ANIM_OVERVIEW_TRANSLATE_X = 7;
public static final int ANIM_ALL_APPS_FADE = 8; public static final int ANIM_OVERVIEW_TRANSLATE_Y = 8;
public static final int ANIM_OVERVIEW_FADE = 9;
public static final int ANIM_ALL_APPS_FADE = 10;
public static final int FLAG_DONT_ANIMATE_OVERVIEW = 1 << 0; public static final int FLAG_DONT_ANIMATE_OVERVIEW = 1 << 0;

View File

@ -69,8 +69,6 @@ public class UiFactory {
return false; return false;
} }
public static void prepareToShowOverview(Launcher launcher) { }
public static void setBackButtonAlpha(Launcher launcher, float alpha, boolean animate) { } public static void setBackButtonAlpha(Launcher launcher, float alpha, boolean animate) { }