Add WorkspaceRevealAnim, successor to StaggeredWorkspaceAnim.
- Added support for widgets for the new close animation. - This anim is used with the new app close. - This anim is not compataible with the old app close, so we need to keep StaggeredWorkspaceAnim in case we turn the app close flag off. - We will also use this anim in the lockscreen to launcher anim, will connect them in a follow up CL. Bug: 188413065 Bug: 173107751 Test: manual Change-Id: Icab3fd700f2c268bb1c4509a37466e4e6748f789
This commit is contained in:
parent
3ed7ee76c4
commit
7d2dfcfb3f
|
@ -75,7 +75,6 @@ import com.android.launcher3.icons.FastBitmapDrawable;
|
|||
import com.android.launcher3.shortcuts.DeepShortcutView;
|
||||
import com.android.launcher3.statehandlers.DepthController;
|
||||
import com.android.launcher3.util.ActivityOptionsWrapper;
|
||||
import com.android.launcher3.util.DynamicResource;
|
||||
import com.android.launcher3.util.MultiValueAlpha;
|
||||
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
|
||||
import com.android.launcher3.util.RunnableList;
|
||||
|
@ -86,8 +85,8 @@ import com.android.quickstep.SystemUiProxy;
|
|||
import com.android.quickstep.TaskViewUtils;
|
||||
import com.android.quickstep.util.MultiValueUpdateListener;
|
||||
import com.android.quickstep.util.RemoteAnimationProvider;
|
||||
import com.android.quickstep.util.StaggeredWorkspaceAnim;
|
||||
import com.android.quickstep.util.SurfaceTransactionApplier;
|
||||
import com.android.quickstep.util.WorkspaceRevealAnim;
|
||||
import com.android.quickstep.views.FloatingWidgetView;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.systemui.shared.system.ActivityCompat;
|
||||
|
@ -1213,10 +1212,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
|||
}
|
||||
});
|
||||
} else {
|
||||
float velocityPxPerS = DynamicResource.provider(mLauncher)
|
||||
.getDimension(R.dimen.unlock_staggered_velocity_dp_per_s);
|
||||
anim.play(new StaggeredWorkspaceAnim(mLauncher, velocityPxPerS, false)
|
||||
.getAnimators());
|
||||
anim.play(new WorkspaceRevealAnim(mLauncher, false).getAnimators());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ import com.android.quickstep.SystemUiProxy;
|
|||
import com.android.quickstep.util.AnimatorControllerWithResistance;
|
||||
import com.android.quickstep.util.LayoutUtils;
|
||||
import com.android.quickstep.util.MotionPauseDetector;
|
||||
import com.android.quickstep.util.StaggeredWorkspaceAnim;
|
||||
import com.android.quickstep.util.WorkspaceRevealAnim;
|
||||
import com.android.quickstep.views.LauncherRecentsView;
|
||||
|
||||
/**
|
||||
|
@ -384,8 +384,7 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
|
|||
updateNonOverviewAnim(targetState, config);
|
||||
nonOverviewAnim = mNonOverviewAnim.getAnimationPlayer();
|
||||
|
||||
new StaggeredWorkspaceAnim(mLauncher, velocity.y, false /* animateOverviewScrim */)
|
||||
.start();
|
||||
new WorkspaceRevealAnim(mLauncher, false /* animateOverviewScrim */).start();
|
||||
} else {
|
||||
boolean canceled = targetState == NORMAL;
|
||||
if (canceled) {
|
||||
|
|
|
@ -102,10 +102,10 @@ import com.android.quickstep.util.MotionPauseDetector;
|
|||
import com.android.quickstep.util.ProtoTracer;
|
||||
import com.android.quickstep.util.RecentsOrientedState;
|
||||
import com.android.quickstep.util.RectFSpringAnim;
|
||||
import com.android.quickstep.util.StaggeredWorkspaceAnim;
|
||||
import com.android.quickstep.util.SurfaceTransactionApplier;
|
||||
import com.android.quickstep.util.SwipePipToHomeAnimator;
|
||||
import com.android.quickstep.util.TransformParams;
|
||||
import com.android.quickstep.util.WorkspaceRevealAnim;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
|
@ -201,7 +201,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
|||
STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN | STATE_LAUNCHER_STARTED;
|
||||
|
||||
public static final long MAX_SWIPE_DURATION = 350;
|
||||
public static final long HOME_DURATION = StaggeredWorkspaceAnim.DURATION_MS;
|
||||
public static final long HOME_DURATION = WorkspaceRevealAnim.DURATION_MS;
|
||||
|
||||
public static final float MIN_PROGRESS_FOR_OVERVIEW = 0.7f;
|
||||
private static final float SWIPE_DURATION_MULTIPLIER =
|
||||
|
@ -1126,6 +1126,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
|||
windowAnim.start(mContext, velocityPxPerMs);
|
||||
mRunningWindowAnim = RunningWindowAnim.wrap(windowAnim);
|
||||
}
|
||||
homeAnimFactory.setSwipeVelocity(velocityPxPerMs.y);
|
||||
homeAnimFactory.playAtomicAnimation(velocityPxPerMs.y);
|
||||
mLauncherTransitionController = null;
|
||||
|
||||
|
|
|
@ -18,13 +18,14 @@ package com.android.quickstep;
|
|||
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
|
||||
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.Utilities.boundToRange;
|
||||
import static com.android.launcher3.Utilities.dpToPx;
|
||||
import static com.android.launcher3.Utilities.mapToRange;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.config.FeatureFlags.PROTOTYPE_APP_CLOSE;
|
||||
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
|
||||
import static com.android.launcher3.views.FloatingIconView.getFloatingIconView;
|
||||
|
||||
import static java.lang.Math.round;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
|
@ -52,10 +53,12 @@ import com.android.launcher3.states.StateAnimationConfig;
|
|||
import com.android.launcher3.util.DynamicResource;
|
||||
import com.android.launcher3.util.ObjectWrapper;
|
||||
import com.android.launcher3.views.FloatingIconView;
|
||||
import com.android.launcher3.views.FloatingView;
|
||||
import com.android.launcher3.widget.LauncherAppWidgetHostView;
|
||||
import com.android.quickstep.util.AppCloseConfig;
|
||||
import com.android.quickstep.util.RectFSpringAnim;
|
||||
import com.android.quickstep.util.StaggeredWorkspaceAnim;
|
||||
import com.android.quickstep.util.WorkspaceRevealAnim;
|
||||
import com.android.quickstep.views.FloatingWidgetView;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
|
@ -112,10 +115,6 @@ public class LauncherSwipeHandlerV2 extends
|
|||
private HomeAnimationFactory createIconHomeAnimationFactory(View workspaceView) {
|
||||
final ResourceProvider rp = DynamicResource.provider(mActivity);
|
||||
final float transY = dpToPx(rp.getFloat(R.dimen.swipe_up_trans_y_dp));
|
||||
float dpPerSecond = dpToPx(rp.getFloat(R.dimen.swipe_up_trans_y_dp_per_s));
|
||||
final float launcherAlphaMax =
|
||||
rp.getFloat(R.dimen.swipe_up_launcher_alpha_max_progress);
|
||||
|
||||
RectF iconLocation = new RectF();
|
||||
FloatingIconView floatingIconView = getFloatingIconView(mActivity, workspaceView,
|
||||
true /* hideOriginal */, iconLocation, false /* isOpening */);
|
||||
|
@ -123,73 +122,25 @@ public class LauncherSwipeHandlerV2 extends
|
|||
// We want the window alpha to be 0 once this threshold is met, so that the
|
||||
// FolderIconView can be seen morphing into the icon shape.
|
||||
float windowAlphaThreshold = 1f - SHAPE_PROGRESS_DURATION;
|
||||
return new LauncherHomeAnimationFactory() {
|
||||
|
||||
return new FloatingViewHomeAnimationFactory(floatingIconView) {
|
||||
|
||||
// There is a delay in loading the icon, so we need to keep the window
|
||||
// opaque until it is ready.
|
||||
private boolean mIsFloatingIconReady = false;
|
||||
|
||||
private @Nullable ValueAnimator mBounceBackAnimator;
|
||||
|
||||
@Override
|
||||
public RectF getWindowTargetRect() {
|
||||
if (PROTOTYPE_APP_CLOSE.get()) {
|
||||
// We want the target rect to be at this offset position, so that all
|
||||
// launcher content can spring back upwards.
|
||||
floatingIconView.setPositionOffsetY(transY);
|
||||
}
|
||||
super.getWindowTargetRect();
|
||||
return iconLocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAnimation(RectFSpringAnim anim) {
|
||||
super.setAnimation(anim);
|
||||
anim.addAnimatorListener(floatingIconView);
|
||||
floatingIconView.setOnTargetChangeListener(anim::onTargetPositionChanged);
|
||||
floatingIconView.setFastFinishRunnable(anim::end);
|
||||
if (PROTOTYPE_APP_CLOSE.get()) {
|
||||
mBounceBackAnimator = bounceBackToRestingPosition();
|
||||
// Use a spring to put drag layer translation back to 0.
|
||||
anim.addAnimatorListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
floatingIconView.setPositionOffsetY(0);
|
||||
mBounceBackAnimator.start();
|
||||
}
|
||||
});
|
||||
|
||||
Workspace workspace = mActivity.getWorkspace();
|
||||
workspace.setPivotToScaleWithSelf(mActivity.getHotseat());
|
||||
}
|
||||
}
|
||||
|
||||
private ValueAnimator bounceBackToRestingPosition() {
|
||||
DragLayer dl = mActivity.getDragLayer();
|
||||
Workspace workspace = mActivity.getWorkspace();
|
||||
Hotseat hotseat = mActivity.getHotseat();
|
||||
|
||||
final float startValue = transY;
|
||||
final float endValue = 0;
|
||||
// Ensures the velocity is always aligned with the direction.
|
||||
float pixelPerSecond = Math.abs(dpPerSecond) * Math.signum(endValue - transY);
|
||||
|
||||
ValueAnimator springTransY = new SpringAnimationBuilder(dl.getContext())
|
||||
.setStiffness(rp.getFloat(R.dimen.swipe_up_trans_y_stiffness))
|
||||
.setDampingRatio(rp.getFloat(R.dimen.swipe_up_trans_y_damping))
|
||||
.setMinimumVisibleChange(1f)
|
||||
.setStartValue(startValue)
|
||||
.setEndValue(endValue)
|
||||
.setStartVelocity(pixelPerSecond)
|
||||
.build(dl, VIEW_TRANSLATE_Y);
|
||||
springTransY.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
dl.setTranslationY(0f);
|
||||
dl.setAlpha(1f);
|
||||
SCALE_PROPERTY.set(workspace, 1f);
|
||||
SCALE_PROPERTY.set(hotseat, 1f);
|
||||
}
|
||||
});
|
||||
return springTransY;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -204,34 +155,15 @@ public class LauncherSwipeHandlerV2 extends
|
|||
@Override
|
||||
public void update(@Nullable AppCloseConfig config, RectF currentRect,
|
||||
float progress, float radius) {
|
||||
super.update(config, currentRect, progress, radius);
|
||||
int fgAlpha = 255;
|
||||
if (config != null && PROTOTYPE_APP_CLOSE.get()) {
|
||||
DragLayer dl = mActivity.getDragLayer();
|
||||
float translationY = config.getWorkspaceTransY();
|
||||
dl.setTranslationY(translationY);
|
||||
|
||||
float alpha = mapToRange(progress, 0, launcherAlphaMax, 0, 1f, LINEAR);
|
||||
dl.setAlpha(Math.min(alpha, 1f));
|
||||
|
||||
float scale = Math.min(1f, config.getWorkspaceScale());
|
||||
SCALE_PROPERTY.set(mActivity.getWorkspace(), scale);
|
||||
SCALE_PROPERTY.set(mActivity.getHotseat(), scale);
|
||||
SCALE_PROPERTY.set(mActivity.getAppsView(), scale);
|
||||
|
||||
progress = config.getInterpolatedProgress();
|
||||
fgAlpha = config.getFgAlpha();
|
||||
}
|
||||
floatingIconView.update(1f, fgAlpha, currentRect, progress,
|
||||
windowAlphaThreshold, radius, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
floatingIconView.fastFinish();
|
||||
if (mBounceBackAnimator != null) {
|
||||
mBounceBackAnimator.cancel();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -246,10 +178,11 @@ public class LauncherSwipeHandlerV2 extends
|
|||
hostView, backgroundLocation, windowSize,
|
||||
mTaskViewSimulator.getCurrentCornerRadius(), isTargetTranslucent);
|
||||
|
||||
return new LauncherHomeAnimationFactory() {
|
||||
return new FloatingViewHomeAnimationFactory(floatingWidgetView) {
|
||||
|
||||
@Override
|
||||
public RectF getWindowTargetRect() {
|
||||
super.getWindowTargetRect();
|
||||
return backgroundLocation;
|
||||
}
|
||||
|
||||
|
@ -260,6 +193,8 @@ public class LauncherSwipeHandlerV2 extends
|
|||
|
||||
@Override
|
||||
public void setAnimation(RectFSpringAnim anim) {
|
||||
super.setAnimation(anim);
|
||||
|
||||
anim.addAnimatorListener(floatingWidgetView);
|
||||
floatingWidgetView.setOnTargetChangeListener(anim::onTargetPositionChanged);
|
||||
floatingWidgetView.setFastFinishRunnable(anim::end);
|
||||
|
@ -273,15 +208,11 @@ public class LauncherSwipeHandlerV2 extends
|
|||
@Override
|
||||
public void update(@Nullable AppCloseConfig config, RectF currentRect,
|
||||
float progress, float radius) {
|
||||
super.update(config, currentRect, progress, radius);
|
||||
floatingWidgetView.update(currentRect, 1 /* floatingWidgetAlpha */,
|
||||
config != null ? config.getFgAlpha() : 1f /* foregroundAlpha */,
|
||||
0 /* fallbackBackgroundAlpha */, 1 - progress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
floatingWidgetView.fastFinish();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -323,6 +254,120 @@ public class LauncherSwipeHandlerV2 extends
|
|||
true /* toRecents */, callback, true /* sendUserLeaveHint */);
|
||||
}
|
||||
|
||||
private class FloatingViewHomeAnimationFactory extends LauncherHomeAnimationFactory {
|
||||
|
||||
private final float mTransY;
|
||||
private final FloatingView mFloatingView;
|
||||
private ValueAnimator mBounceBackAnimator;
|
||||
private final AnimatorSet mWorkspaceReveal;
|
||||
|
||||
FloatingViewHomeAnimationFactory(FloatingView floatingView) {
|
||||
mFloatingView = floatingView;
|
||||
|
||||
ResourceProvider rp = DynamicResource.provider(mActivity);
|
||||
mTransY = dpToPx(rp.getFloat(R.dimen.swipe_up_trans_y_dp));
|
||||
|
||||
mWorkspaceReveal = PROTOTYPE_APP_CLOSE.get()
|
||||
? new WorkspaceRevealAnim(mActivity, true /* animateScrim */).getAnimators()
|
||||
: null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull RectF getWindowTargetRect() {
|
||||
if (PROTOTYPE_APP_CLOSE.get()) {
|
||||
// We want the target rect to be at this offset position, so that all
|
||||
// launcher content can spring back upwards.
|
||||
mFloatingView.setPositionOffsetY(mTransY);
|
||||
}
|
||||
return super.getWindowTargetRect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldPlayAtomicWorkspaceReveal() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(@Nullable AppCloseConfig config, RectF currentRect, float progress,
|
||||
float radius) {
|
||||
if (config != null && PROTOTYPE_APP_CLOSE.get()) {
|
||||
DragLayer dl = mActivity.getDragLayer();
|
||||
float translationY = config.getWorkspaceTransY();
|
||||
dl.setTranslationY(translationY);
|
||||
|
||||
long duration = mWorkspaceReveal.getDuration();
|
||||
long playTime = boundToRange(round(duration * progress), 0, duration);
|
||||
mWorkspaceReveal.setCurrentPlayTime(playTime);
|
||||
}
|
||||
}
|
||||
|
||||
protected void bounceBackToRestingPosition() {
|
||||
final float startValue = mTransY;
|
||||
final float endValue = 0;
|
||||
// Ensures the velocity is always aligned with the direction.
|
||||
float pixelPerSecond = Math.abs(mSwipeVelocity) * Math.signum(endValue - mTransY);
|
||||
|
||||
DragLayer dl = mActivity.getDragLayer();
|
||||
Workspace workspace = mActivity.getWorkspace();
|
||||
Hotseat hotseat = mActivity.getHotseat();
|
||||
|
||||
ResourceProvider rp = DynamicResource.provider(mActivity);
|
||||
ValueAnimator springTransY = new SpringAnimationBuilder(dl.getContext())
|
||||
.setStiffness(rp.getFloat(R.dimen.swipe_up_trans_y_stiffness))
|
||||
.setDampingRatio(rp.getFloat(R.dimen.swipe_up_trans_y_damping))
|
||||
.setMinimumVisibleChange(1f)
|
||||
.setStartValue(startValue)
|
||||
.setEndValue(endValue)
|
||||
.setStartVelocity(pixelPerSecond)
|
||||
.build(dl, VIEW_TRANSLATE_Y);
|
||||
springTransY.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
dl.setTranslationY(0f);
|
||||
dl.setAlpha(1f);
|
||||
SCALE_PROPERTY.set(workspace, 1f);
|
||||
SCALE_PROPERTY.set(hotseat, 1f);
|
||||
}
|
||||
});
|
||||
|
||||
mBounceBackAnimator = springTransY;
|
||||
mBounceBackAnimator.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAnimation(RectFSpringAnim anim) {
|
||||
if (PROTOTYPE_APP_CLOSE.get()) {
|
||||
// Use a spring to put drag layer translation back to 0.
|
||||
anim.addAnimatorListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mFloatingView.setPositionOffsetY(0);
|
||||
bounceBackToRestingPosition();
|
||||
}
|
||||
});
|
||||
|
||||
// Will be updated manually below so that the two animations are in sync.
|
||||
mWorkspaceReveal.start();
|
||||
mWorkspaceReveal.pause();
|
||||
|
||||
anim.addAnimatorListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mWorkspaceReveal.end();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
mFloatingView.fastFinish();
|
||||
if (mBounceBackAnimator != null) {
|
||||
mBounceBackAnimator.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class LauncherHomeAnimationFactory extends HomeAnimationFactory {
|
||||
@NonNull
|
||||
@Override
|
||||
|
@ -336,8 +381,12 @@ public class LauncherSwipeHandlerV2 extends
|
|||
|
||||
@Override
|
||||
public void playAtomicAnimation(float velocity) {
|
||||
new StaggeredWorkspaceAnim(mActivity, velocity, true /* animateOverviewScrim */,
|
||||
!PROTOTYPE_APP_CLOSE.get()).start();
|
||||
if (!PROTOTYPE_APP_CLOSE.get()) {
|
||||
new StaggeredWorkspaceAnim(mActivity, velocity, true /* animateOverviewScrim */)
|
||||
.start();
|
||||
} else if (shouldPlayAtomicWorkspaceReveal()) {
|
||||
new WorkspaceRevealAnim(mActivity, true).start();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -129,6 +129,7 @@ public abstract class SwipeUpAnimationLogic {
|
|||
}
|
||||
|
||||
protected abstract class HomeAnimationFactory {
|
||||
protected float mSwipeVelocity;
|
||||
|
||||
public @NonNull RectF getWindowTargetRect() {
|
||||
PagedOrientationHandler orientationHandler = getOrientationHandler();
|
||||
|
@ -152,10 +153,18 @@ public abstract class SwipeUpAnimationLogic {
|
|||
|
||||
public abstract @NonNull AnimatorPlaybackController createActivityAnimationToHome();
|
||||
|
||||
public void setSwipeVelocity(float velocity) {
|
||||
mSwipeVelocity = velocity;
|
||||
}
|
||||
|
||||
public void playAtomicAnimation(float velocity) {
|
||||
// No-op
|
||||
}
|
||||
|
||||
public boolean shouldPlayAtomicWorkspaceReveal() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setAnimation(RectFSpringAnim anim) { }
|
||||
|
||||
public boolean keepWindowOpaque() { return false; }
|
||||
|
|
|
@ -30,7 +30,7 @@ import com.android.launcher3.states.StateAnimationConfig;
|
|||
|
||||
/**
|
||||
* Runs an animation from overview to home. Currently, this animation is just a wrapper around the
|
||||
* normal state transition and may play a {@link StaggeredWorkspaceAnim} if we're starting from an
|
||||
* normal state transition and may play a {@link WorkspaceRevealAnim} if we're starting from an
|
||||
* upward fling.
|
||||
*/
|
||||
public class OverviewToHomeAnim {
|
||||
|
@ -51,7 +51,7 @@ public class OverviewToHomeAnim {
|
|||
|
||||
/**
|
||||
* Starts the animation. If velocity < 0 (i.e. upwards), also plays a
|
||||
* {@link StaggeredWorkspaceAnim}.
|
||||
* {@link WorkspaceRevealAnim}.
|
||||
*/
|
||||
public void animateWithVelocity(float velocity) {
|
||||
StateManager<LauncherState> stateManager = mLauncher.getStateManager();
|
||||
|
@ -61,18 +61,18 @@ public class OverviewToHomeAnim {
|
|||
}
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
|
||||
boolean playStaggeredWorkspaceAnim = velocity < 0;
|
||||
if (playStaggeredWorkspaceAnim) {
|
||||
StaggeredWorkspaceAnim staggeredWorkspaceAnim = new StaggeredWorkspaceAnim(
|
||||
mLauncher, velocity, false /* animateOverviewScrim */);
|
||||
staggeredWorkspaceAnim.addAnimatorListener(new AnimationSuccessListener() {
|
||||
boolean playWorkspaceRevealAnim = velocity < 0;
|
||||
if (playWorkspaceRevealAnim) {
|
||||
WorkspaceRevealAnim workspaceRevealAnim = new WorkspaceRevealAnim(mLauncher,
|
||||
false /* animateOverviewScrim */);
|
||||
workspaceRevealAnim.addAnimatorListener(new AnimationSuccessListener() {
|
||||
@Override
|
||||
public void onAnimationSuccess(Animator animator) {
|
||||
mIsHomeStaggeredAnimFinished = true;
|
||||
maybeOverviewToHomeAnimComplete();
|
||||
}
|
||||
});
|
||||
anim.play(staggeredWorkspaceAnim.getAnimators());
|
||||
anim.play(workspaceRevealAnim.getAnimators());
|
||||
} else {
|
||||
mIsHomeStaggeredAnimFinished = true;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Copyright (C) 2021 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.quickstep.util;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
|
||||
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.SKIP_DEPTH_CONTROLLER;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.SKIP_SCRIM;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.BaseQuickstepLauncher;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Workspace;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.statehandlers.DepthController;
|
||||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
import com.android.launcher3.util.DynamicResource;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.systemui.plugins.ResourceProvider;
|
||||
|
||||
/**
|
||||
* Creates an animation that reveals the workspace.
|
||||
* This is used in conjunction with the swipe up to home animation.
|
||||
*/
|
||||
public class WorkspaceRevealAnim {
|
||||
|
||||
// Should be used for animations running alongside this WorkspaceRevealAnim.
|
||||
public static final int DURATION_MS = 350;
|
||||
|
||||
private final float mScaleStart;
|
||||
private final AnimatorSet mAnimators = new AnimatorSet();
|
||||
|
||||
public WorkspaceRevealAnim(Launcher launcher, boolean animateOverviewScrim) {
|
||||
prepareToAnimate(launcher, animateOverviewScrim);
|
||||
|
||||
ResourceProvider rp = DynamicResource.provider(launcher);
|
||||
mScaleStart = rp.getFloat(R.dimen.swipe_up_scale_start);
|
||||
|
||||
Workspace workspace = launcher.getWorkspace();
|
||||
workspace.setPivotToScaleWithSelf(launcher.getHotseat());
|
||||
|
||||
// Add reveal animations.
|
||||
addRevealAnimatorsForView(workspace);
|
||||
addRevealAnimatorsForView(launcher.getHotseat());
|
||||
|
||||
// Add overview scrim animation.
|
||||
if (animateOverviewScrim) {
|
||||
PendingAnimation overviewScrimBuilder = new PendingAnimation(DURATION_MS);
|
||||
launcher.getWorkspace().getStateTransitionAnimation()
|
||||
.setScrim(overviewScrimBuilder, NORMAL, new StateAnimationConfig());
|
||||
mAnimators.play(overviewScrimBuilder.buildAnim());
|
||||
}
|
||||
|
||||
// Add depth controller animation.
|
||||
if (launcher instanceof BaseQuickstepLauncher) {
|
||||
PendingAnimation depthBuilder = new PendingAnimation(DURATION_MS);
|
||||
DepthController depth = ((BaseQuickstepLauncher) launcher).getDepthController();
|
||||
depth.setStateWithAnimation(NORMAL, new StateAnimationConfig(), depthBuilder);
|
||||
mAnimators.play(depthBuilder.buildAnim());
|
||||
}
|
||||
|
||||
// Add sysui scrim animation.
|
||||
mAnimators.play(launcher.getRootView().getSysUiScrim().createSysuiMultiplierAnim(0f, 1f));
|
||||
|
||||
mAnimators.setDuration(DURATION_MS);
|
||||
mAnimators.setInterpolator(Interpolators.DECELERATED_EASE);
|
||||
}
|
||||
|
||||
private void addRevealAnimatorsForView(View v) {
|
||||
ObjectAnimator scale = ObjectAnimator.ofFloat(v, SCALE_PROPERTY, mScaleStart, 1f);
|
||||
scale.setDuration(DURATION_MS);
|
||||
scale.setInterpolator(Interpolators.DECELERATED_EASE);
|
||||
mAnimators.play(scale);
|
||||
|
||||
ObjectAnimator alpha = ObjectAnimator.ofFloat(v, View.ALPHA, 0, 1f);
|
||||
alpha.setDuration(DURATION_MS);
|
||||
alpha.setInterpolator(Interpolators.DECELERATED_EASE);
|
||||
mAnimators.play(alpha);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup workspace with 0 duration.
|
||||
*/
|
||||
private void prepareToAnimate(Launcher launcher, boolean animateOverviewScrim) {
|
||||
StateAnimationConfig config = new StateAnimationConfig();
|
||||
config.animFlags = SKIP_OVERVIEW | SKIP_DEPTH_CONTROLLER | SKIP_SCRIM;
|
||||
config.duration = 0;
|
||||
// setRecentsAttachedToAppWindow() will animate recents out.
|
||||
launcher.getStateManager().createAtomicAnimation(BACKGROUND_APP, NORMAL, config).start();
|
||||
|
||||
// Stop scrolling so that it doesn't interfere with the translation offscreen.
|
||||
launcher.<RecentsView>getOverviewPanel().getScroller().forceFinished(true);
|
||||
|
||||
if (animateOverviewScrim) {
|
||||
launcher.getWorkspace().getStateTransitionAnimation()
|
||||
.setScrim(NO_ANIM_PROPERTY_SETTER, BACKGROUND_APP, config);
|
||||
}
|
||||
}
|
||||
|
||||
public AnimatorSet getAnimators() {
|
||||
return mAnimators;
|
||||
}
|
||||
|
||||
public WorkspaceRevealAnim addAnimatorListener(Animator.AnimatorListener listener) {
|
||||
mAnimators.addListener(listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the animation.
|
||||
*/
|
||||
public void start() {
|
||||
mAnimators.start();
|
||||
}
|
||||
}
|
|
@ -34,6 +34,7 @@ import com.android.launcher3.Launcher;
|
|||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.dragndrop.DragLayer;
|
||||
import com.android.launcher3.views.FloatingView;
|
||||
import com.android.launcher3.views.ListenerView;
|
||||
import com.android.launcher3.widget.LauncherAppWidgetHostView;
|
||||
import com.android.launcher3.widget.RoundedCornerEnforcement;
|
||||
|
@ -41,7 +42,7 @@ import com.android.launcher3.widget.RoundedCornerEnforcement;
|
|||
/** A view that mimics an App Widget through a launch animation. */
|
||||
@TargetApi(Build.VERSION_CODES.S)
|
||||
public class FloatingWidgetView extends FrameLayout implements AnimatorListener,
|
||||
OnGlobalLayoutListener {
|
||||
OnGlobalLayoutListener, FloatingView {
|
||||
private static final Matrix sTmpMatrix = new Matrix();
|
||||
|
||||
private final Launcher mLauncher;
|
||||
|
@ -59,6 +60,8 @@ public class FloatingWidgetView extends FrameLayout implements AnimatorListener,
|
|||
private Runnable mOnTargetChangeRunnable;
|
||||
private boolean mAppTargetIsTranslucent;
|
||||
|
||||
private float mIconOffsetY;
|
||||
|
||||
public FloatingWidgetView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
@ -129,6 +132,7 @@ public class FloatingWidgetView extends FrameLayout implements AnimatorListener,
|
|||
}
|
||||
|
||||
/** Callback at the end or early exit of the animation. */
|
||||
@Override
|
||||
public void fastFinish() {
|
||||
if (isUninitialized()) return;
|
||||
Runnable fastFinishRunnable = mFastFinishRunnable;
|
||||
|
@ -192,6 +196,12 @@ public class FloatingWidgetView extends FrameLayout implements AnimatorListener,
|
|||
positionViews();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPositionOffsetY(float y) {
|
||||
mIconOffsetY = y;
|
||||
onGlobalLayout();
|
||||
}
|
||||
|
||||
/** Sets the layout parameters of the floating view and its background view child. */
|
||||
private void positionViews() {
|
||||
LayoutParams layoutParams = (LayoutParams) getLayoutParams();
|
||||
|
@ -200,7 +210,7 @@ public class FloatingWidgetView extends FrameLayout implements AnimatorListener,
|
|||
|
||||
// FloatingWidgetView layout is forced LTR
|
||||
mBackgroundView.setTranslationX(mBackgroundPosition.left);
|
||||
mBackgroundView.setTranslationY(mBackgroundPosition.top);
|
||||
mBackgroundView.setTranslationY(mBackgroundPosition.top + mIconOffsetY);
|
||||
LayoutParams backgroundParams = (LayoutParams) mBackgroundView.getLayoutParams();
|
||||
backgroundParams.leftMargin = 0;
|
||||
backgroundParams.topMargin = 0;
|
||||
|
@ -215,7 +225,8 @@ public class FloatingWidgetView extends FrameLayout implements AnimatorListener,
|
|||
sTmpMatrix.setTranslate(-mBackgroundOffset.left - mAppWidgetView.getLeft(),
|
||||
-mBackgroundOffset.top - mAppWidgetView.getTop());
|
||||
sTmpMatrix.postScale(foregroundScale, foregroundScale);
|
||||
sTmpMatrix.postTranslate(mBackgroundPosition.left, mBackgroundPosition.top);
|
||||
sTmpMatrix.postTranslate(mBackgroundPosition.left, mBackgroundPosition.top
|
||||
+ mIconOffsetY);
|
||||
mForegroundOverlayView.setMatrix(sTmpMatrix);
|
||||
}
|
||||
}
|
||||
|
@ -240,6 +251,7 @@ public class FloatingWidgetView extends FrameLayout implements AnimatorListener,
|
|||
}
|
||||
|
||||
private void recycle() {
|
||||
mIconOffsetY = 0;
|
||||
mEndRunnable = null;
|
||||
mFastFinishRunnable = null;
|
||||
mOnTargetChangeRunnable = null;
|
||||
|
|
|
@ -126,7 +126,7 @@
|
|||
|
||||
<item name="swipe_up_rect_xy_fling_friction" type="dimen" format="float">1.5</item>
|
||||
|
||||
<item name="swipe_up_scale_start" type="dimen" format="float">0.98</item>
|
||||
<item name="swipe_up_scale_start" type="dimen" format="float">0.88</item>
|
||||
<item name="swipe_up_duration" type="dimen" format="float">400</item>
|
||||
|
||||
<item name="swipe_up_trans_y_dp" type="dimen" format="float">4.5</item>
|
||||
|
|
|
@ -63,7 +63,7 @@ import com.android.launcher3.shortcuts.DeepShortcutView;
|
|||
*/
|
||||
@TargetApi(Build.VERSION_CODES.Q)
|
||||
public class FloatingIconView extends FrameLayout implements
|
||||
Animator.AnimatorListener, OnGlobalLayoutListener {
|
||||
Animator.AnimatorListener, OnGlobalLayoutListener, FloatingView {
|
||||
|
||||
private static final String TAG = FloatingIconView.class.getSimpleName();
|
||||
|
||||
|
@ -443,6 +443,7 @@ public class FloatingIconView extends FrameLayout implements
|
|||
mFastFinishRunnable = runnable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fastFinish() {
|
||||
if (mFastFinishRunnable != null) {
|
||||
mFastFinishRunnable.run();
|
||||
|
@ -475,9 +476,7 @@ public class FloatingIconView extends FrameLayout implements
|
|||
@Override
|
||||
public void onAnimationRepeat(Animator animator) {}
|
||||
|
||||
/**
|
||||
* Offsets and updates the position of this view by {@param y}.
|
||||
*/
|
||||
@Override
|
||||
public void setPositionOffsetY(float y) {
|
||||
mIconOffsetY = y;
|
||||
onGlobalLayout();
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (C) 2021 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.views;
|
||||
|
||||
/**
|
||||
* Shared interface for floating views.
|
||||
*/
|
||||
public interface FloatingView {
|
||||
|
||||
/**
|
||||
* Offsets and updates the position of this view by {@param y}.
|
||||
*/
|
||||
void setPositionOffsetY(float y);
|
||||
|
||||
/**
|
||||
* Fast finish the animation.
|
||||
*/
|
||||
void fastFinish();
|
||||
}
|
Loading…
Reference in New Issue