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:
Jon Miranda 2021-05-14 13:07:43 -07:00 committed by Jonathan Miranda
parent 3ed7ee76c4
commit 7d2dfcfb3f
11 changed files with 347 additions and 113 deletions

View File

@ -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());
}
}
}

View File

@ -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) {

View File

@ -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;

View File

@ -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

View File

@ -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; }

View File

@ -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;
}

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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>

View File

@ -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();

View File

@ -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();
}