Merge remote-tracking branch 'aosp/android12L-release' into 12.1-dev
This commit is contained in:
@@ -28,19 +28,24 @@ import static com.android.launcher3.LauncherAnimUtils.VIEW_BACKGROUND_COLOR;
|
||||
import static com.android.launcher3.LauncherState.ALL_APPS;
|
||||
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.Utilities.mapBoundToRange;
|
||||
import static com.android.launcher3.Utilities.postAsyncCallback;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
|
||||
import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL_1_5;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7;
|
||||
import static com.android.launcher3.anim.Interpolators.EXAGGERATED_EASE;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_BACK_SWIPE_HOME_ANIMATION;
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_SCRIM_FOR_APP_LAUNCH;
|
||||
import static com.android.launcher3.config.FeatureFlags.KEYGUARD_ANIMATION;
|
||||
import static com.android.launcher3.config.FeatureFlags.SEPARATE_RECENTS_ACTIVITY;
|
||||
import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_TRANSITIONS;
|
||||
import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
|
||||
import static com.android.launcher3.statehandlers.DepthController.DEPTH;
|
||||
import static com.android.launcher3.util.DisplayController.getSingleFrameMs;
|
||||
import static com.android.quickstep.TaskUtils.taskIsATargetWithMode;
|
||||
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
|
||||
import static com.android.launcher3.views.FloatingIconView.getFloatingIconView;
|
||||
import static com.android.quickstep.TaskViewUtils.findTaskViewToLaunch;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.getWindowCornerRadius;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.supportsRoundedCornersOnWindows;
|
||||
@@ -52,26 +57,31 @@ import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Pair;
|
||||
import android.util.Size;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.View;
|
||||
import android.view.ViewRootImpl;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.PathInterpolator;
|
||||
|
||||
@@ -86,8 +96,12 @@ import com.android.launcher3.dragndrop.DragLayer;
|
||||
import com.android.launcher3.icons.FastBitmapDrawable;
|
||||
import com.android.launcher3.shortcuts.DeepShortcutView;
|
||||
import com.android.launcher3.statehandlers.DepthController;
|
||||
import com.android.launcher3.taskbar.LauncherTaskbarUIController;
|
||||
import com.android.launcher3.touch.PagedOrientationHandler;
|
||||
import com.android.launcher3.util.ActivityOptionsWrapper;
|
||||
import com.android.launcher3.util.DynamicResource;
|
||||
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
|
||||
import com.android.launcher3.util.ObjectWrapper;
|
||||
import com.android.launcher3.util.RunnableList;
|
||||
import com.android.launcher3.views.FloatingIconView;
|
||||
import com.android.launcher3.views.ScrimView;
|
||||
@@ -96,7 +110,9 @@ import com.android.quickstep.RemoteAnimationTargets;
|
||||
import com.android.quickstep.SystemUiProxy;
|
||||
import com.android.quickstep.TaskViewUtils;
|
||||
import com.android.quickstep.util.MultiValueUpdateListener;
|
||||
import com.android.quickstep.util.RectFSpringAnim;
|
||||
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;
|
||||
@@ -144,21 +160,11 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
private static final String CONTROL_REMOTE_APP_TRANSITION_PERMISSION =
|
||||
"android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS";
|
||||
|
||||
private static final long APP_LAUNCH_DURATION = 450;
|
||||
// Use a shorter duration for x or y translation to create a curve effect
|
||||
private static final long APP_LAUNCH_CURVED_DURATION = 250;
|
||||
private static final long APP_LAUNCH_DURATION = 500;
|
||||
|
||||
private static final long APP_LAUNCH_ALPHA_DURATION = 50;
|
||||
private static final long APP_LAUNCH_ALPHA_START_DELAY = 25;
|
||||
|
||||
// We scale the durations for the downward app launch animations (minus the scale animation).
|
||||
private static final float APP_LAUNCH_DOWN_DUR_SCALE_FACTOR = 0.8f;
|
||||
private static final long APP_LAUNCH_DOWN_DURATION =
|
||||
(long) (APP_LAUNCH_DURATION * APP_LAUNCH_DOWN_DUR_SCALE_FACTOR);
|
||||
private static final long APP_LAUNCH_DOWN_CURVED_DURATION =
|
||||
(long) (APP_LAUNCH_CURVED_DURATION * APP_LAUNCH_DOWN_DUR_SCALE_FACTOR);
|
||||
private static final long APP_LAUNCH_ALPHA_DOWN_DURATION =
|
||||
(long) (APP_LAUNCH_ALPHA_DURATION * APP_LAUNCH_DOWN_DUR_SCALE_FACTOR);
|
||||
|
||||
public static final int ANIMATION_NAV_FADE_IN_DURATION = 266;
|
||||
public static final int ANIMATION_NAV_FADE_OUT_DURATION = 133;
|
||||
public static final long ANIMATION_DELAY_NAV_FADE_IN =
|
||||
@@ -168,12 +174,11 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
public static final Interpolator NAV_FADE_OUT_INTERPOLATOR =
|
||||
new PathInterpolator(0.2f, 0f, 1f, 1f);
|
||||
|
||||
private static final long CROP_DURATION = 375;
|
||||
private static final long RADIUS_DURATION = 375;
|
||||
|
||||
public static final int RECENTS_LAUNCH_DURATION = 336;
|
||||
private static final int LAUNCHER_RESUME_START_DELAY = 100;
|
||||
private static final int CLOSING_TRANSITION_DURATION_MS = 250;
|
||||
public static final int SPLIT_LAUNCH_DURATION = 370;
|
||||
public static final int SPLIT_DIVIDER_ANIM_DURATION = 100;
|
||||
|
||||
public static final int CONTENT_ALPHA_DURATION = 217;
|
||||
protected static final int CONTENT_SCALE_DURATION = 350;
|
||||
@@ -224,6 +229,9 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
// Will never be larger than MAX_NUM_TASKS
|
||||
private LinkedHashMap<Integer, Pair<Integer, Integer>> mTaskStartParams;
|
||||
|
||||
private final Interpolator mOpeningXInterpolator;
|
||||
private final Interpolator mOpeningInterpolator;
|
||||
|
||||
public QuickstepTransitionManager(Context context) {
|
||||
mLauncher = Launcher.cast(Launcher.getLauncher(context));
|
||||
mDragLayer = mLauncher.getDragLayer();
|
||||
@@ -250,6 +258,10 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
SystemUiProxy.INSTANCE.get(mLauncher).setStartingWindowListener(
|
||||
mStartingWindowListener);
|
||||
}
|
||||
|
||||
mOpeningXInterpolator = AnimationUtils.loadInterpolator(context, R.interpolator.app_open_x);
|
||||
mOpeningInterpolator = AnimationUtils.loadInterpolator(context,
|
||||
R.interpolator.three_point_fast_out_extra_slow_in);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -277,7 +289,8 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
long statusBarTransitionDelay = duration - STATUS_BAR_TRANSITION_DURATION
|
||||
- STATUS_BAR_TRANSITION_PRE_DELAY;
|
||||
RemoteAnimationAdapterCompat adapterCompat =
|
||||
new RemoteAnimationAdapterCompat(runner, duration, statusBarTransitionDelay);
|
||||
new RemoteAnimationAdapterCompat(runner, duration, statusBarTransitionDelay,
|
||||
mLauncher.getIApplicationThread());
|
||||
return new ActivityOptionsWrapper(
|
||||
ActivityOptionsCompat.makeRemoteAnimation(adapterCompat), onEndCallback);
|
||||
}
|
||||
@@ -356,7 +369,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
if (launcherClosing) {
|
||||
// Delay animation by a frame to avoid jank.
|
||||
Pair<AnimatorSet, Runnable> launcherContentAnimator =
|
||||
getLauncherContentAnimator(true /* isAppOpening */, startDelay);
|
||||
getLauncherContentAnimator(true /* isAppOpening */, startDelay, false);
|
||||
anim.play(launcherContentAnimator.first);
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
@@ -430,6 +443,10 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
4 - rotationChange);
|
||||
}
|
||||
}
|
||||
if (mDeviceProfile.isTaskbarPresentInApps) {
|
||||
// Animate to above the taskbar.
|
||||
bounds.bottom -= target.contentInsets.bottom;
|
||||
}
|
||||
return bounds;
|
||||
}
|
||||
|
||||
@@ -449,9 +466,10 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
* @param isAppOpening True when this is called when an app is opening.
|
||||
* False when this is called when an app is closing.
|
||||
* @param startDelay Start delay duration.
|
||||
* @param skipAllAppsScale True if we want to avoid scaling All Apps
|
||||
*/
|
||||
private Pair<AnimatorSet, Runnable> getLauncherContentAnimator(boolean isAppOpening,
|
||||
int startDelay) {
|
||||
int startDelay, boolean skipAllAppsScale) {
|
||||
AnimatorSet launcherAnimator = new AnimatorSet();
|
||||
Runnable endListener;
|
||||
|
||||
@@ -469,7 +487,6 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
final float startAlpha = appsView.getAlpha();
|
||||
final float startScale = SCALE_PROPERTY.get(appsView);
|
||||
appsView.setAlpha(alphas[0]);
|
||||
SCALE_PROPERTY.set(appsView, scales[0]);
|
||||
|
||||
ObjectAnimator alpha = ObjectAnimator.ofFloat(appsView, View.ALPHA, alphas);
|
||||
alpha.setDuration(CONTENT_ALPHA_DURATION);
|
||||
@@ -481,12 +498,16 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
appsView.setLayerType(View.LAYER_TYPE_NONE, null);
|
||||
}
|
||||
});
|
||||
ObjectAnimator scale = ObjectAnimator.ofFloat(appsView, SCALE_PROPERTY, scales);
|
||||
scale.setInterpolator(AGGRESSIVE_EASE);
|
||||
scale.setDuration(CONTENT_SCALE_DURATION);
|
||||
|
||||
if (!skipAllAppsScale) {
|
||||
SCALE_PROPERTY.set(appsView, scales[0]);
|
||||
ObjectAnimator scale = ObjectAnimator.ofFloat(appsView, SCALE_PROPERTY, scales);
|
||||
scale.setInterpolator(AGGRESSIVE_EASE);
|
||||
scale.setDuration(CONTENT_SCALE_DURATION);
|
||||
launcherAnimator.play(scale);
|
||||
}
|
||||
|
||||
launcherAnimator.play(alpha);
|
||||
launcherAnimator.play(scale);
|
||||
|
||||
endListener = () -> {
|
||||
appsView.setAlpha(startAlpha);
|
||||
@@ -514,7 +535,10 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
|
||||
final boolean scrimEnabled = ENABLE_SCRIM_FOR_APP_LAUNCH.get();
|
||||
if (scrimEnabled) {
|
||||
int scrimColor = ColorTokens.OverviewScrim.resolveColor(mLauncher);
|
||||
boolean useTaskbarColor = mDeviceProfile.isTaskbarPresentInApps;
|
||||
int scrimColor = useTaskbarColor
|
||||
? mLauncher.getResources().getColor(R.color.taskbar_background)
|
||||
: ColorTokens.OverviewScrim.resolveColor(mLauncher);
|
||||
int scrimColorTrans = ColorUtils.setAlphaComponent(scrimColor, 0);
|
||||
int[] colors = isAppOpening
|
||||
? new int[]{scrimColorTrans, scrimColor}
|
||||
@@ -527,6 +551,30 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
colors);
|
||||
scrim.setDuration(CONTENT_SCRIM_DURATION);
|
||||
scrim.setInterpolator(DEACCEL_1_5);
|
||||
|
||||
if (useTaskbarColor) {
|
||||
// Hide the taskbar background color since it would duplicate the scrim.
|
||||
scrim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
LauncherTaskbarUIController taskbarUIController =
|
||||
mLauncher.getTaskbarUIController();
|
||||
if (taskbarUIController != null) {
|
||||
taskbarUIController.forceHideBackground(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
LauncherTaskbarUIController taskbarUIController =
|
||||
mLauncher.getTaskbarUIController();
|
||||
if (taskbarUIController != null) {
|
||||
taskbarUIController.forceHideBackground(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
launcherAnimator.play(scrim);
|
||||
}
|
||||
}
|
||||
@@ -619,10 +667,10 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
AnimOpenProperties prop = new AnimOpenProperties(mLauncher.getResources(), mDeviceProfile,
|
||||
windowTargetBounds, launcherIconBounds, v, dragLayerBounds[0], dragLayerBounds[1],
|
||||
hasSplashScreen, floatingView.isDifferentFromAppIcon());
|
||||
int left = (int) (prop.cropCenterXStart - prop.cropWidthStart / 2);
|
||||
int top = (int) (prop.cropCenterYStart - prop.cropHeightStart / 2);
|
||||
int right = (int) (left + prop.cropWidthStart);
|
||||
int bottom = (int) (top + prop.cropHeightStart);
|
||||
int left = prop.cropCenterXStart - prop.cropWidthStart / 2;
|
||||
int top = prop.cropCenterYStart - prop.cropHeightStart / 2;
|
||||
int right = left + prop.cropWidthStart;
|
||||
int bottom = top + prop.cropHeightStart;
|
||||
// Set the crop here so we can calculate the corner radius below.
|
||||
crop.set(left, top, right, bottom);
|
||||
|
||||
@@ -641,6 +689,10 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
if (v instanceof BubbleTextView) {
|
||||
((BubbleTextView) v).setStayPressed(false);
|
||||
}
|
||||
LauncherTaskbarUIController taskbarController = mLauncher.getTaskbarUIController();
|
||||
if (taskbarController != null) {
|
||||
taskbarController.showEdu();
|
||||
}
|
||||
openingTargets.release();
|
||||
}
|
||||
});
|
||||
@@ -649,31 +701,33 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
? Math.max(crop.width(), crop.height()) / 2f * IconShapeManager.getWindowTransitionRadius(mLauncher)
|
||||
: 0f;
|
||||
final float finalWindowRadius = mDeviceProfile.isMultiWindowMode
|
||||
? 0 : getWindowCornerRadius(mLauncher.getResources());
|
||||
? 0 : getWindowCornerRadius(mLauncher);
|
||||
final float finalShadowRadius = appTargetsAreTranslucent ? 0 : mMaxShadowRadius;
|
||||
|
||||
MultiValueUpdateListener listener = new MultiValueUpdateListener() {
|
||||
FloatProp mDx = new FloatProp(0, prop.dX, 0, prop.xDuration, AGGRESSIVE_EASE);
|
||||
FloatProp mDy = new FloatProp(0, prop.dY, 0, prop.yDuration, AGGRESSIVE_EASE);
|
||||
FloatProp mDx = new FloatProp(0, prop.dX, 0, APP_LAUNCH_DURATION,
|
||||
mOpeningXInterpolator);
|
||||
FloatProp mDy = new FloatProp(0, prop.dY, 0, APP_LAUNCH_DURATION,
|
||||
mOpeningInterpolator);
|
||||
|
||||
FloatProp mIconScaleToFitScreen = new FloatProp(prop.initialAppIconScale,
|
||||
prop.finalAppIconScale, 0, APP_LAUNCH_DURATION, EXAGGERATED_EASE);
|
||||
prop.finalAppIconScale, 0, APP_LAUNCH_DURATION, mOpeningInterpolator);
|
||||
FloatProp mIconAlpha = new FloatProp(prop.iconAlphaStart, 0f,
|
||||
APP_LAUNCH_ALPHA_START_DELAY, prop.alphaDuration, LINEAR);
|
||||
APP_LAUNCH_ALPHA_START_DELAY, APP_LAUNCH_ALPHA_DURATION, LINEAR);
|
||||
|
||||
FloatProp mWindowRadius = new FloatProp(initialWindowRadius, finalWindowRadius, 0,
|
||||
RADIUS_DURATION, EXAGGERATED_EASE);
|
||||
APP_LAUNCH_DURATION, mOpeningInterpolator);
|
||||
FloatProp mShadowRadius = new FloatProp(0, finalShadowRadius, 0,
|
||||
APP_LAUNCH_DURATION, EXAGGERATED_EASE);
|
||||
APP_LAUNCH_DURATION, mOpeningInterpolator);
|
||||
|
||||
FloatProp mCropRectCenterX = new FloatProp(prop.cropCenterXStart, prop.cropCenterXEnd,
|
||||
0, CROP_DURATION, EXAGGERATED_EASE);
|
||||
0, APP_LAUNCH_DURATION, mOpeningInterpolator);
|
||||
FloatProp mCropRectCenterY = new FloatProp(prop.cropCenterYStart, prop.cropCenterYEnd,
|
||||
0, CROP_DURATION, EXAGGERATED_EASE);
|
||||
0, APP_LAUNCH_DURATION, mOpeningInterpolator);
|
||||
FloatProp mCropRectWidth = new FloatProp(prop.cropWidthStart, prop.cropWidthEnd, 0,
|
||||
CROP_DURATION, EXAGGERATED_EASE);
|
||||
APP_LAUNCH_DURATION, mOpeningInterpolator);
|
||||
FloatProp mCropRectHeight = new FloatProp(prop.cropHeightStart, prop.cropHeightEnd, 0,
|
||||
CROP_DURATION, EXAGGERATED_EASE);
|
||||
APP_LAUNCH_DURATION, mOpeningInterpolator);
|
||||
|
||||
FloatProp mNavFadeOut = new FloatProp(1f, 0f, 0, ANIMATION_NAV_FADE_OUT_DURATION,
|
||||
NAV_FADE_OUT_INTERPOLATOR);
|
||||
@@ -810,7 +864,13 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
// Since we added a start delay, call update here to init the FloatingIconView properly.
|
||||
listener.onUpdate(0, true /* initOnly */);
|
||||
|
||||
animatorSet.playTogether(appAnimator, getBackgroundAnimator(appTargets));
|
||||
// If app targets are translucent, do not animate the background as it causes a visible
|
||||
// flicker when it resets itself at the end of its animation.
|
||||
if (appTargetsAreTranslucent) {
|
||||
animatorSet.play(appAnimator);
|
||||
} else {
|
||||
animatorSet.playTogether(appAnimator, getBackgroundAnimator());
|
||||
}
|
||||
return animatorSet;
|
||||
}
|
||||
|
||||
@@ -838,7 +898,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
}
|
||||
|
||||
final float finalWindowRadius = mDeviceProfile.isMultiWindowMode
|
||||
? 0 : getWindowCornerRadius(mLauncher.getResources());
|
||||
? 0 : getWindowCornerRadius(mLauncher);
|
||||
final FloatingWidgetView floatingView = FloatingWidgetView.getFloatingWidgetView(mLauncher,
|
||||
v, widgetBackgroundBounds,
|
||||
new Size(windowTargetBounds.width(), windowTargetBounds.height()),
|
||||
@@ -875,22 +935,23 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
WIDGET_CROSSFADE_DURATION_MILLIS / 2 /* delay */,
|
||||
WIDGET_CROSSFADE_DURATION_MILLIS / 2 /* duration */, LINEAR);
|
||||
final FloatProp mWindowRadius = new FloatProp(initialWindowRadius, finalWindowRadius,
|
||||
0 /* start */, RADIUS_DURATION, LINEAR);
|
||||
final FloatProp mCornerRadiusProgress = new FloatProp(0, 1, 0, RADIUS_DURATION, LINEAR);
|
||||
0 /* start */, APP_LAUNCH_DURATION, mOpeningInterpolator);
|
||||
final FloatProp mCornerRadiusProgress = new FloatProp(0, 1, 0, APP_LAUNCH_DURATION,
|
||||
mOpeningInterpolator);
|
||||
|
||||
// Window & widget background positioning bounds
|
||||
final FloatProp mDx = new FloatProp(widgetBackgroundBounds.centerX(),
|
||||
windowTargetBounds.centerX(), 0 /* delay */, APP_LAUNCH_CURVED_DURATION,
|
||||
EXAGGERATED_EASE);
|
||||
windowTargetBounds.centerX(), 0 /* delay */, APP_LAUNCH_DURATION,
|
||||
mOpeningXInterpolator);
|
||||
final FloatProp mDy = new FloatProp(widgetBackgroundBounds.centerY(),
|
||||
windowTargetBounds.centerY(), 0 /* delay */, APP_LAUNCH_DURATION,
|
||||
EXAGGERATED_EASE);
|
||||
mOpeningInterpolator);
|
||||
final FloatProp mWidth = new FloatProp(widgetBackgroundBounds.width(),
|
||||
windowTargetBounds.width(), 0 /* delay */, APP_LAUNCH_DURATION,
|
||||
EXAGGERATED_EASE);
|
||||
mOpeningInterpolator);
|
||||
final FloatProp mHeight = new FloatProp(widgetBackgroundBounds.height(),
|
||||
windowTargetBounds.height(), 0 /* delay */, APP_LAUNCH_DURATION,
|
||||
EXAGGERATED_EASE);
|
||||
mOpeningInterpolator);
|
||||
|
||||
final FloatProp mNavFadeOut = new FloatProp(1f, 0f, 0, ANIMATION_NAV_FADE_OUT_DURATION,
|
||||
NAV_FADE_OUT_INTERPOLATOR);
|
||||
@@ -946,11 +1007,20 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
}
|
||||
});
|
||||
|
||||
animatorSet.playTogether(appAnimator, getBackgroundAnimator(appTargets));
|
||||
// If app targets are translucent, do not animate the background as it causes a visible
|
||||
// flicker when it resets itself at the end of its animation.
|
||||
if (appTargetsAreTranslucent) {
|
||||
animatorSet.play(appAnimator);
|
||||
} else {
|
||||
animatorSet.playTogether(appAnimator, getBackgroundAnimator());
|
||||
}
|
||||
return animatorSet;
|
||||
}
|
||||
|
||||
private ObjectAnimator getBackgroundAnimator(RemoteAnimationTargetCompat[] appTargets) {
|
||||
/**
|
||||
* Returns animator that controls depth/blur of the background.
|
||||
*/
|
||||
private ObjectAnimator getBackgroundAnimator() {
|
||||
// When launching an app from overview that doesn't map to a task, we still want to just
|
||||
// blur the wallpaper instead of the launcher surface as well
|
||||
boolean allowBlurringLauncher = mLauncher.getStateManager().getState() != OVERVIEW;
|
||||
@@ -1020,7 +1090,8 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
new RemoteAnimationAdapterCompat(
|
||||
new LauncherAnimationRunner(mHandler, mWallpaperOpenRunner,
|
||||
false /* startAtFrontOfQueue */),
|
||||
CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */));
|
||||
CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */,
|
||||
mLauncher.getIApplicationThread()));
|
||||
|
||||
if (KEYGUARD_ANIMATION.get()) {
|
||||
mKeyguardGoingAwayRunner = createWallpaperOpenRunner(true /* fromUnlock */);
|
||||
@@ -1030,7 +1101,8 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
new LauncherAnimationRunner(
|
||||
mHandler, mKeyguardGoingAwayRunner,
|
||||
true /* startAtFrontOfQueue */),
|
||||
CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */));
|
||||
CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */,
|
||||
mLauncher.getIApplicationThread()));
|
||||
}
|
||||
|
||||
new ActivityCompat(mLauncher).registerRemoteAnimations(definition);
|
||||
@@ -1049,8 +1121,8 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
mWallpaperOpenTransitionRunner = createWallpaperOpenRunner(false /* fromUnlock */);
|
||||
mLauncherOpenTransition = RemoteAnimationAdapterCompat.buildRemoteTransition(
|
||||
new LauncherAnimationRunner(mHandler, mWallpaperOpenTransitionRunner,
|
||||
false /* startAtFrontOfQueue */));
|
||||
mLauncherOpenTransition.addHomeOpenCheck();
|
||||
false /* startAtFrontOfQueue */), mLauncher.getIApplicationThread());
|
||||
mLauncherOpenTransition.addHomeOpenCheck(mLauncher.getComponentName());
|
||||
SystemUiProxy.INSTANCE.getNoCreate().registerRemoteTransition(mLauncherOpenTransition);
|
||||
}
|
||||
}
|
||||
@@ -1091,7 +1163,16 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
}
|
||||
|
||||
private boolean launcherIsATargetWithMode(RemoteAnimationTargetCompat[] targets, int mode) {
|
||||
return taskIsATargetWithMode(targets, mLauncher.getTaskId(), mode);
|
||||
for (RemoteAnimationTargetCompat target : targets) {
|
||||
if (target.mode == mode && target.taskInfo != null
|
||||
// Compare component name instead of task-id because transitions will promote
|
||||
// the target up to the root task while getTaskId returns the leaf.
|
||||
&& target.taskInfo.topActivity != null
|
||||
&& target.taskInfo.topActivity.equals(mLauncher.getComponentName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1111,7 +1192,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
ValueAnimator unlockAnimator = ValueAnimator.ofFloat(0, 1);
|
||||
unlockAnimator.setDuration(CLOSING_TRANSITION_DURATION_MS);
|
||||
float cornerRadius = mDeviceProfile.isMultiWindowMode ? 0 :
|
||||
QuickStepContract.getWindowCornerRadius(mLauncher.getResources());
|
||||
QuickStepContract.getWindowCornerRadius(mLauncher);
|
||||
unlockAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
@@ -1141,10 +1222,181 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
}
|
||||
|
||||
/**
|
||||
* Animator that controls the transformations of the windows the targets that are closing.
|
||||
* Returns view on launcher that corresponds to the closing app in the list of app targets
|
||||
*/
|
||||
private Animator getClosingWindowAnimators(RemoteAnimationTargetCompat[] appTargets,
|
||||
RemoteAnimationTargetCompat[] wallpaperTargets) {
|
||||
private @Nullable View findLauncherView(RemoteAnimationTargetCompat[] appTargets) {
|
||||
for (RemoteAnimationTargetCompat appTarget : appTargets) {
|
||||
if (appTarget.mode == MODE_CLOSING) {
|
||||
View launcherView = findLauncherView(appTarget);
|
||||
if (launcherView != null) {
|
||||
return launcherView;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns view on launcher that corresponds to the {@param runningTaskTarget}.
|
||||
*/
|
||||
private @Nullable View findLauncherView(RemoteAnimationTargetCompat runningTaskTarget) {
|
||||
if (runningTaskTarget == null || runningTaskTarget.taskInfo == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final ComponentName[] taskInfoActivities = new ComponentName[] {
|
||||
runningTaskTarget.taskInfo.baseActivity,
|
||||
runningTaskTarget.taskInfo.origActivity,
|
||||
runningTaskTarget.taskInfo.realActivity,
|
||||
runningTaskTarget.taskInfo.topActivity};
|
||||
|
||||
String packageName = null;
|
||||
for (ComponentName component : taskInfoActivities) {
|
||||
if (component != null && component.getPackageName() != null) {
|
||||
packageName = component.getPackageName();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (packageName == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Find the associated item info for the launch cookie (if available), note that predicted
|
||||
// apps actually have an id of -1, so use another default id here
|
||||
final ArrayList<IBinder> launchCookies = runningTaskTarget.taskInfo.launchCookies == null
|
||||
? new ArrayList<>()
|
||||
: runningTaskTarget.taskInfo.launchCookies;
|
||||
|
||||
int launchCookieItemId = NO_MATCHING_ID;
|
||||
for (IBinder cookie : launchCookies) {
|
||||
Integer itemId = ObjectWrapper.unwrap(cookie);
|
||||
if (itemId != null) {
|
||||
launchCookieItemId = itemId;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return mLauncher.getFirstMatchForAppClose(launchCookieItemId,
|
||||
packageName, UserHandle.of(runningTaskTarget.taskInfo.userId));
|
||||
}
|
||||
|
||||
private @NonNull RectF getDefaultWindowTargetRect() {
|
||||
RecentsView recentsView = mLauncher.getOverviewPanel();
|
||||
PagedOrientationHandler orientationHandler = recentsView.getPagedOrientationHandler();
|
||||
DeviceProfile dp = mLauncher.getDeviceProfile();
|
||||
final int halfIconSize = dp.iconSizePx / 2;
|
||||
float primaryDimension = orientationHandler
|
||||
.getPrimaryValue(dp.availableWidthPx, dp.availableHeightPx);
|
||||
float secondaryDimension = orientationHandler
|
||||
.getSecondaryValue(dp.availableWidthPx, dp.availableHeightPx);
|
||||
final float targetX = primaryDimension / 2f;
|
||||
final float targetY = secondaryDimension - dp.hotseatBarSizePx;
|
||||
return new RectF(targetX - halfIconSize, targetY - halfIconSize,
|
||||
targetX + halfIconSize, targetY + halfIconSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closing animator that animates the window into its final location on the workspace.
|
||||
*/
|
||||
private void getClosingWindowAnimators(AnimatorSet animation,
|
||||
RemoteAnimationTargetCompat[] targets, View launcherView, PointF velocityPxPerS) {
|
||||
FloatingIconView floatingIconView = null;
|
||||
FloatingWidgetView floatingWidget = null;
|
||||
RectF targetRect = new RectF();
|
||||
|
||||
RemoteAnimationTargetCompat runningTaskTarget = null;
|
||||
boolean isTransluscent = false;
|
||||
for (RemoteAnimationTargetCompat target : targets) {
|
||||
if (target.mode == MODE_CLOSING) {
|
||||
runningTaskTarget = target;
|
||||
isTransluscent = runningTaskTarget.isTranslucent;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Get floating view and target rect.
|
||||
if (launcherView instanceof LauncherAppWidgetHostView) {
|
||||
Size windowSize = new Size(mDeviceProfile.availableWidthPx,
|
||||
mDeviceProfile.availableHeightPx);
|
||||
int fallbackBackgroundColor =
|
||||
FloatingWidgetView.getDefaultBackgroundColor(mLauncher, runningTaskTarget);
|
||||
floatingWidget = FloatingWidgetView.getFloatingWidgetView(mLauncher,
|
||||
(LauncherAppWidgetHostView) launcherView, targetRect, windowSize,
|
||||
mDeviceProfile.isMultiWindowMode ? 0 : getWindowCornerRadius(mLauncher),
|
||||
isTransluscent, fallbackBackgroundColor);
|
||||
} else if (launcherView != null) {
|
||||
floatingIconView = getFloatingIconView(mLauncher, launcherView,
|
||||
true /* hideOriginal */, targetRect, false /* isOpening */);
|
||||
} else {
|
||||
targetRect.set(getDefaultWindowTargetRect());
|
||||
}
|
||||
|
||||
final RectF startRect = new RectF(0, 0, mDeviceProfile.widthPx, mDeviceProfile.heightPx);
|
||||
RectFSpringAnim anim = new RectFSpringAnim(startRect, targetRect, mLauncher,
|
||||
mDeviceProfile);
|
||||
|
||||
// Hook up floating views to the closing window animators.
|
||||
final int rotationChange = getRotationChange(targets);
|
||||
Rect windowTargetBounds = getWindowTargetBounds(targets, rotationChange);
|
||||
if (floatingIconView != null) {
|
||||
anim.addAnimatorListener(floatingIconView);
|
||||
floatingIconView.setOnTargetChangeListener(anim::onTargetPositionChanged);
|
||||
floatingIconView.setFastFinishRunnable(anim::end);
|
||||
FloatingIconView finalFloatingIconView = floatingIconView;
|
||||
|
||||
// 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.
|
||||
final float windowAlphaThreshold = 1f - SHAPE_PROGRESS_DURATION;
|
||||
|
||||
RectFSpringAnim.OnUpdateListener runner = new SpringAnimRunner(targets, targetRect,
|
||||
windowTargetBounds) {
|
||||
@Override
|
||||
public void onUpdate(RectF currentRectF, float progress) {
|
||||
finalFloatingIconView.update(1f, 255 /* fgAlpha */, currentRectF, progress,
|
||||
windowAlphaThreshold, getCornerRadius(progress), false);
|
||||
|
||||
super.onUpdate(currentRectF, progress);
|
||||
}
|
||||
};
|
||||
anim.addOnUpdateListener(runner);
|
||||
} else if (floatingWidget != null) {
|
||||
anim.addAnimatorListener(floatingWidget);
|
||||
floatingWidget.setOnTargetChangeListener(anim::onTargetPositionChanged);
|
||||
floatingWidget.setFastFinishRunnable(anim::end);
|
||||
|
||||
final float floatingWidgetAlpha = isTransluscent ? 0 : 1;
|
||||
FloatingWidgetView finalFloatingWidget = floatingWidget;
|
||||
RectFSpringAnim.OnUpdateListener runner = new SpringAnimRunner(targets, targetRect,
|
||||
windowTargetBounds) {
|
||||
@Override
|
||||
public void onUpdate(RectF currentRectF, float progress) {
|
||||
final float fallbackBackgroundAlpha =
|
||||
1 - mapBoundToRange(progress, 0.8f, 1, 0, 1, EXAGGERATED_EASE);
|
||||
final float foregroundAlpha =
|
||||
mapBoundToRange(progress, 0.5f, 1, 0, 1, EXAGGERATED_EASE);
|
||||
finalFloatingWidget.update(currentRectF, floatingWidgetAlpha, foregroundAlpha,
|
||||
fallbackBackgroundAlpha, 1 - progress);
|
||||
|
||||
super.onUpdate(currentRectF, progress);
|
||||
}
|
||||
};
|
||||
anim.addOnUpdateListener(runner);
|
||||
}
|
||||
|
||||
// Use a fixed velocity to start the animation.
|
||||
animation.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
anim.start(mLauncher, velocityPxPerS);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Closing window animator that moves the window down and offscreen.
|
||||
*/
|
||||
private Animator getFallbackClosingWindowAnimators(RemoteAnimationTargetCompat[] appTargets) {
|
||||
final int rotationChange = getRotationChange(appTargets);
|
||||
SurfaceTransactionApplier surfaceApplier = new SurfaceTransactionApplier(mDragLayer);
|
||||
Matrix matrix = new Matrix();
|
||||
@@ -1153,7 +1405,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
ValueAnimator closingAnimator = ValueAnimator.ofFloat(0, 1);
|
||||
int duration = CLOSING_TRANSITION_DURATION_MS;
|
||||
float windowCornerRadius = mDeviceProfile.isMultiWindowMode
|
||||
? 0 : getWindowCornerRadius(mLauncher.getResources());
|
||||
? 0 : getWindowCornerRadius(mLauncher);
|
||||
float startShadowRadius = areAllTargetsTranslucent(appTargets) ? 0 : mMaxShadowRadius;
|
||||
closingAnimator.setDuration(duration);
|
||||
closingAnimator.addUpdateListener(new MultiValueUpdateListener() {
|
||||
@@ -1283,7 +1535,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
LauncherAnimationRunner.AnimationResult result) {
|
||||
if (mLauncher.isDestroyed()) {
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
anim.play(getClosingWindowAnimators(appTargets, wallpaperTargets));
|
||||
anim.play(getFallbackClosingWindowAnimators(appTargets));
|
||||
result.setAnimation(anim, mLauncher.getApplicationContext());
|
||||
return;
|
||||
}
|
||||
@@ -1310,9 +1562,39 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
|
||||
if (anim == null) {
|
||||
anim = new AnimatorSet();
|
||||
anim.play(mFromUnlock
|
||||
? getUnlockWindowAnimator(appTargets, wallpaperTargets)
|
||||
: getClosingWindowAnimators(appTargets, wallpaperTargets));
|
||||
|
||||
final boolean launcherIsForceInvisibleOrOpening = mLauncher.isForceInvisible()
|
||||
|| launcherIsATargetWithMode(appTargets, MODE_OPENING);
|
||||
|
||||
View launcherView = findLauncherView(appTargets);
|
||||
boolean playFallBackAnimation = (launcherView == null
|
||||
&& launcherIsForceInvisibleOrOpening)
|
||||
|| mLauncher.getWorkspace().isOverlayShown();
|
||||
|
||||
boolean playWorkspaceReveal = true;
|
||||
boolean skipAllAppsScale = false;
|
||||
if (mFromUnlock) {
|
||||
anim.play(getUnlockWindowAnimator(appTargets, wallpaperTargets));
|
||||
} else if (ENABLE_BACK_SWIPE_HOME_ANIMATION.get()
|
||||
&& !playFallBackAnimation) {
|
||||
// Use a fixed velocity to start the animation.
|
||||
float velocityPxPerS = DynamicResource.provider(mLauncher)
|
||||
.getDimension(R.dimen.unlock_staggered_velocity_dp_per_s);
|
||||
PointF velocity = new PointF(0, -velocityPxPerS);
|
||||
getClosingWindowAnimators(anim, appTargets, launcherView, velocity);
|
||||
if (!mLauncher.isInState(LauncherState.ALL_APPS)) {
|
||||
anim.play(new StaggeredWorkspaceAnim(mLauncher, velocity.y,
|
||||
true /* animateOverviewScrim */, launcherView).getAnimators());
|
||||
// We play StaggeredWorkspaceAnim as a part of the closing window animation.
|
||||
playWorkspaceReveal = false;
|
||||
} else {
|
||||
// Skip scaling all apps, otherwise FloatingIconView will get wrong
|
||||
// layout bounds.
|
||||
skipAllAppsScale = true;
|
||||
}
|
||||
} else {
|
||||
anim.play(getFallbackClosingWindowAnimators(appTargets));
|
||||
}
|
||||
|
||||
// Normally, we run the launcher content animation when we are transitioning
|
||||
// home, but if home is already visible, then we don't want to animate the
|
||||
@@ -1322,8 +1604,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
// targets list because it is already visible). In that case, we force
|
||||
// invisibility on touch down, and only reset it after the animation to home
|
||||
// is initialized.
|
||||
if (launcherIsATargetWithMode(appTargets, MODE_OPENING)
|
||||
|| mLauncher.isForceInvisible()) {
|
||||
if (launcherIsForceInvisibleOrOpening) {
|
||||
addCujInstrumentation(
|
||||
anim, InteractionJankMonitorWrapper.CUJ_APP_CLOSE_TO_HOME);
|
||||
// Only register the content animation for cancellation when state changes
|
||||
@@ -1331,7 +1612,8 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
|
||||
if (mLauncher.isInState(LauncherState.ALL_APPS)) {
|
||||
Pair<AnimatorSet, Runnable> contentAnimator =
|
||||
getLauncherContentAnimator(false, LAUNCHER_RESUME_START_DELAY);
|
||||
getLauncherContentAnimator(false, LAUNCHER_RESUME_START_DELAY,
|
||||
skipAllAppsScale);
|
||||
anim.play(contentAnimator.first);
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
@@ -1340,7 +1622,9 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
}
|
||||
});
|
||||
} else {
|
||||
anim.play(new WorkspaceRevealAnim(mLauncher, false).getAnimators());
|
||||
if (playWorkspaceReveal) {
|
||||
anim.play(new WorkspaceRevealAnim(mLauncher, false).getAnimators());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1427,10 +1711,6 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
public final float dX;
|
||||
public final float dY;
|
||||
|
||||
public final long xDuration;
|
||||
public final long yDuration;
|
||||
public final long alphaDuration;
|
||||
|
||||
public final float initialAppIconScale;
|
||||
public final float finalAppIconScale;
|
||||
|
||||
@@ -1462,14 +1742,6 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
dX = centerX - launcherIconBounds.centerX();
|
||||
dY = centerY - launcherIconBounds.centerY();
|
||||
|
||||
boolean useUpwardAnimation = launcherIconBounds.top > centerY
|
||||
|| Math.abs(dY) < dp.cellHeightPx;
|
||||
xDuration = useUpwardAnimation ? APP_LAUNCH_CURVED_DURATION
|
||||
: APP_LAUNCH_DOWN_DURATION;
|
||||
yDuration = useUpwardAnimation ? APP_LAUNCH_DURATION
|
||||
: APP_LAUNCH_DOWN_CURVED_DURATION;
|
||||
alphaDuration = useUpwardAnimation ? APP_LAUNCH_ALPHA_DURATION
|
||||
: APP_LAUNCH_ALPHA_DOWN_DURATION;
|
||||
iconAlphaStart = hasSplashScreen && !hasDifferentAppIcon ? 0 : 1f;
|
||||
|
||||
final int windowIconSize = ResourceUtils.getDimenByName("starting_surface_icon_size",
|
||||
@@ -1501,4 +1773,101 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
mTransitionManager.mTaskStartParams.put(taskId, Pair.create(supportedType, color));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* RectFSpringAnim update listener to be used for app to home animation.
|
||||
*/
|
||||
private class SpringAnimRunner implements RectFSpringAnim.OnUpdateListener {
|
||||
private final RemoteAnimationTargetCompat[] mAppTargets;
|
||||
private final Matrix mMatrix = new Matrix();
|
||||
private final Point mTmpPos = new Point();
|
||||
private final Rect mCurrentRect = new Rect();
|
||||
private final float mStartRadius;
|
||||
private final float mEndRadius;
|
||||
private final SurfaceTransactionApplier mSurfaceApplier;
|
||||
private final Rect mWindowTargetBounds = new Rect();
|
||||
|
||||
private final Rect mTmpRect = new Rect();
|
||||
|
||||
SpringAnimRunner(RemoteAnimationTargetCompat[] appTargets, RectF targetRect,
|
||||
Rect windowTargetBounds) {
|
||||
mAppTargets = appTargets;
|
||||
mStartRadius = QuickStepContract.getWindowCornerRadius(mLauncher);
|
||||
mEndRadius = Math.max(1, targetRect.width()) / 2f;
|
||||
mSurfaceApplier = new SurfaceTransactionApplier(mDragLayer);
|
||||
mWindowTargetBounds.set(windowTargetBounds);
|
||||
}
|
||||
|
||||
public float getCornerRadius(float progress) {
|
||||
return Utilities.mapRange(progress, mStartRadius, mEndRadius);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate(RectF currentRectF, float progress) {
|
||||
SurfaceParams[] params = new SurfaceParams[mAppTargets.length];
|
||||
for (int i = mAppTargets.length - 1; i >= 0; i--) {
|
||||
RemoteAnimationTargetCompat target = mAppTargets[i];
|
||||
SurfaceParams.Builder builder = new SurfaceParams.Builder(target.leash);
|
||||
|
||||
if (target.localBounds != null) {
|
||||
mTmpPos.set(target.localBounds.left, target.localBounds.top);
|
||||
} else {
|
||||
mTmpPos.set(target.position.x, target.position.y);
|
||||
}
|
||||
|
||||
if (target.mode == MODE_CLOSING) {
|
||||
currentRectF.round(mCurrentRect);
|
||||
|
||||
// Scale the target window to match the currentRectF.
|
||||
final float scale;
|
||||
|
||||
// We need to infer the crop (we crop the window to match the currentRectF).
|
||||
if (mWindowTargetBounds.height() > mWindowTargetBounds.width()) {
|
||||
scale = Math.min(1f, currentRectF.width() / mWindowTargetBounds.width());
|
||||
|
||||
int unscaledHeight = (int) (mCurrentRect.height() * (1f / scale));
|
||||
int croppedHeight = mWindowTargetBounds.height() - unscaledHeight;
|
||||
mTmpRect.set(0, 0, mWindowTargetBounds.width(),
|
||||
mWindowTargetBounds.height() - croppedHeight);
|
||||
} else {
|
||||
scale = Math.min(1f, currentRectF.height() / mWindowTargetBounds.height());
|
||||
|
||||
int unscaledWidth = (int) (mCurrentRect.width() * (1f / scale));
|
||||
int croppedWidth = mWindowTargetBounds.width() - unscaledWidth;
|
||||
mTmpRect.set(0, 0, mWindowTargetBounds.width() - croppedWidth,
|
||||
mWindowTargetBounds.height());
|
||||
}
|
||||
|
||||
// Match size and position of currentRect.
|
||||
mMatrix.setScale(scale, scale);
|
||||
mMatrix.postTranslate(mCurrentRect.left, mCurrentRect.top);
|
||||
|
||||
builder.withMatrix(mMatrix)
|
||||
.withWindowCrop(mTmpRect)
|
||||
.withAlpha(getWindowAlpha(progress))
|
||||
.withCornerRadius(getCornerRadius(progress) / scale);
|
||||
} else if (target.mode == MODE_OPENING) {
|
||||
mMatrix.setTranslate(mTmpPos.x, mTmpPos.y);
|
||||
builder.withMatrix(mMatrix)
|
||||
.withAlpha(1f);
|
||||
}
|
||||
params[i] = builder.build();
|
||||
}
|
||||
mSurfaceApplier.scheduleApply(params);
|
||||
}
|
||||
|
||||
protected float getWindowAlpha(float progress) {
|
||||
// Alpha interpolates between [1, 0] between progress values [start, end]
|
||||
final float start = 0f;
|
||||
final float end = 0.85f;
|
||||
|
||||
if (progress <= start) {
|
||||
return 1f;
|
||||
}
|
||||
if (progress >= end) {
|
||||
return 0f;
|
||||
}
|
||||
return Utilities.mapToRange(progress, start, end, 1, 0, ACCEL_1_5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user