use of com.android.quickstep.util.MultiValueUpdateListener in project android_packages_apps_Launcher3 by crdroidandroid.
the class QuickstepTransitionManager method getOpeningWindowAnimators.
/**
* @return Animator that controls the window of the opening targets from app icons.
*/
private Animator getOpeningWindowAnimators(View v, RemoteAnimationTargetCompat[] appTargets, RemoteAnimationTargetCompat[] wallpaperTargets, RemoteAnimationTargetCompat[] nonAppTargets, Rect windowTargetBounds, boolean appTargetsAreTranslucent, int rotationChange) {
RectF launcherIconBounds = new RectF();
FloatingIconView floatingView = FloatingIconView.getFloatingIconView(mLauncher, v, !appTargetsAreTranslucent, launcherIconBounds, true);
Rect crop = new Rect();
Matrix matrix = new Matrix();
RemoteAnimationTargets openingTargets = new RemoteAnimationTargets(appTargets, wallpaperTargets, nonAppTargets, MODE_OPENING);
SurfaceTransactionApplier surfaceApplier = new SurfaceTransactionApplier(floatingView);
openingTargets.addReleaseCheck(surfaceApplier);
RemoteAnimationTargetCompat navBarTarget = openingTargets.getNavBarRemoteAnimationTarget();
int[] dragLayerBounds = new int[2];
mDragLayer.getLocationOnScreen(dragLayerBounds);
final boolean hasSplashScreen;
if (supportsSSplashScreen()) {
int taskId = openingTargets.getFirstAppTargetTaskId();
Pair<Integer, Integer> defaultParams = Pair.create(STARTING_WINDOW_TYPE_NONE, 0);
Pair<Integer, Integer> taskParams = mTaskStartParams.getOrDefault(taskId, defaultParams);
mTaskStartParams.remove(taskId);
hasSplashScreen = taskParams.first == STARTING_WINDOW_TYPE_SPLASH_SCREEN;
} else {
hasSplashScreen = false;
}
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);
// Set the crop here so we can calculate the corner radius below.
crop.set(left, top, right, bottom);
RectF floatingIconBounds = new RectF();
RectF tmpRectF = new RectF();
Point tmpPos = new Point();
AnimatorSet animatorSet = new AnimatorSet();
ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
appAnimator.setDuration(APP_LAUNCH_DURATION);
appAnimator.setInterpolator(LINEAR);
appAnimator.addListener(floatingView);
appAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (v instanceof BubbleTextView) {
((BubbleTextView) v).setStayPressed(false);
}
openingTargets.release();
}
});
final float initialWindowRadius = supportsRoundedCornersOnWindows(mLauncher.getResources()) ? Math.max(crop.width(), crop.height()) / 2f : 0f;
final float finalWindowRadius = mDeviceProfile.isMultiWindowMode ? 0 : getWindowCornerRadius(mLauncher.getResources());
final float finalShadowRadius = appTargetsAreTranslucent ? 0 : mMaxShadowRadius;
MultiValueUpdateListener listener = new MultiValueUpdateListener() {
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, mOpeningInterpolator);
FloatProp mIconAlpha = new FloatProp(prop.iconAlphaStart, 0f, APP_LAUNCH_ALPHA_START_DELAY, APP_LAUNCH_ALPHA_DURATION, LINEAR);
FloatProp mWindowRadius = new FloatProp(initialWindowRadius, finalWindowRadius, 0, APP_LAUNCH_DURATION, mOpeningInterpolator);
FloatProp mShadowRadius = new FloatProp(0, finalShadowRadius, 0, APP_LAUNCH_DURATION, mOpeningInterpolator);
FloatProp mCropRectCenterX = new FloatProp(prop.cropCenterXStart, prop.cropCenterXEnd, 0, APP_LAUNCH_DURATION, mOpeningInterpolator);
FloatProp mCropRectCenterY = new FloatProp(prop.cropCenterYStart, prop.cropCenterYEnd, 0, APP_LAUNCH_DURATION, mOpeningInterpolator);
FloatProp mCropRectWidth = new FloatProp(prop.cropWidthStart, prop.cropWidthEnd, 0, APP_LAUNCH_DURATION, mOpeningInterpolator);
FloatProp mCropRectHeight = new FloatProp(prop.cropHeightStart, prop.cropHeightEnd, 0, APP_LAUNCH_DURATION, mOpeningInterpolator);
FloatProp mNavFadeOut = new FloatProp(1f, 0f, 0, ANIMATION_NAV_FADE_OUT_DURATION, NAV_FADE_OUT_INTERPOLATOR);
FloatProp mNavFadeIn = new FloatProp(0f, 1f, ANIMATION_DELAY_NAV_FADE_IN, ANIMATION_NAV_FADE_IN_DURATION, NAV_FADE_IN_INTERPOLATOR);
@Override
public void onUpdate(float percent, boolean initOnly) {
// Calculate the size of the scaled icon.
float iconWidth = launcherIconBounds.width() * mIconScaleToFitScreen.value;
float iconHeight = launcherIconBounds.height() * mIconScaleToFitScreen.value;
int left = (int) (mCropRectCenterX.value - mCropRectWidth.value / 2);
int top = (int) (mCropRectCenterY.value - mCropRectHeight.value / 2);
int right = (int) (left + mCropRectWidth.value);
int bottom = (int) (top + mCropRectHeight.value);
crop.set(left, top, right, bottom);
final int windowCropWidth = crop.width();
final int windowCropHeight = crop.height();
if (rotationChange != 0) {
Utilities.rotateBounds(crop, mDeviceProfile.widthPx, mDeviceProfile.heightPx, rotationChange);
}
// Scale the size of the icon to match the size of the window crop.
float scaleX = iconWidth / windowCropWidth;
float scaleY = iconHeight / windowCropHeight;
float scale = Math.min(1f, Math.max(scaleX, scaleY));
float scaledCropWidth = windowCropWidth * scale;
float scaledCropHeight = windowCropHeight * scale;
float offsetX = (scaledCropWidth - iconWidth) / 2;
float offsetY = (scaledCropHeight - iconHeight) / 2;
// Calculate the window position to match the icon position.
tmpRectF.set(launcherIconBounds);
tmpRectF.offset(dragLayerBounds[0], dragLayerBounds[1]);
tmpRectF.offset(mDx.value, mDy.value);
Utilities.scaleRectFAboutCenter(tmpRectF, mIconScaleToFitScreen.value);
float windowTransX0 = tmpRectF.left - offsetX - crop.left * scale;
float windowTransY0 = tmpRectF.top - offsetY - crop.top * scale;
// Calculate the icon position.
floatingIconBounds.set(launcherIconBounds);
floatingIconBounds.offset(mDx.value, mDy.value);
Utilities.scaleRectFAboutCenter(floatingIconBounds, mIconScaleToFitScreen.value);
floatingIconBounds.left -= offsetX;
floatingIconBounds.top -= offsetY;
floatingIconBounds.right += offsetX;
floatingIconBounds.bottom += offsetY;
if (initOnly) {
// For the init pass, we want full alpha since the window is not yet ready.
floatingView.update(1f, 255, floatingIconBounds, percent, 0f, mWindowRadius.value * scale, true);
return;
}
ArrayList<SurfaceParams> params = new ArrayList<>();
for (int i = appTargets.length - 1; i >= 0; i--) {
RemoteAnimationTargetCompat target = appTargets[i];
SurfaceParams.Builder builder = new SurfaceParams.Builder(target.leash);
if (target.mode == MODE_OPENING) {
matrix.setScale(scale, scale);
if (rotationChange == 1) {
matrix.postTranslate(windowTransY0, mDeviceProfile.widthPx - (windowTransX0 + scaledCropWidth));
} else if (rotationChange == 2) {
matrix.postTranslate(mDeviceProfile.widthPx - (windowTransX0 + scaledCropWidth), mDeviceProfile.heightPx - (windowTransY0 + scaledCropHeight));
} else if (rotationChange == 3) {
matrix.postTranslate(mDeviceProfile.heightPx - (windowTransY0 + scaledCropHeight), windowTransX0);
} else {
matrix.postTranslate(windowTransX0, windowTransY0);
}
floatingView.update(mIconAlpha.value, 255, floatingIconBounds, percent, 0f, mWindowRadius.value * scale, true);
builder.withMatrix(matrix).withWindowCrop(crop).withAlpha(1f - mIconAlpha.value).withCornerRadius(mWindowRadius.value).withShadowRadius(mShadowRadius.value);
} else if (target.mode == MODE_CLOSING) {
if (target.localBounds != null) {
final Rect localBounds = target.localBounds;
tmpPos.set(target.localBounds.left, target.localBounds.top);
} else {
tmpPos.set(target.position.x, target.position.y);
}
final Rect crop = new Rect(target.screenSpaceBounds);
crop.offsetTo(0, 0);
if ((rotationChange % 2) == 1) {
int tmp = crop.right;
crop.right = crop.bottom;
crop.bottom = tmp;
tmp = tmpPos.x;
tmpPos.x = tmpPos.y;
tmpPos.y = tmp;
}
matrix.setTranslate(tmpPos.x, tmpPos.y);
builder.withMatrix(matrix).withWindowCrop(crop).withAlpha(1f);
}
params.add(builder.build());
}
if (navBarTarget != null) {
final SurfaceParams.Builder navBuilder = new SurfaceParams.Builder(navBarTarget.leash);
if (mNavFadeIn.value > mNavFadeIn.getStartValue()) {
matrix.setScale(scale, scale);
matrix.postTranslate(windowTransX0, windowTransY0);
navBuilder.withMatrix(matrix).withWindowCrop(crop).withAlpha(mNavFadeIn.value);
} else {
navBuilder.withAlpha(mNavFadeOut.value);
}
params.add(navBuilder.build());
}
surfaceApplier.scheduleApply(params.toArray(new SurfaceParams[params.size()]));
}
};
appAnimator.addUpdateListener(listener);
// Since we added a start delay, call update here to init the FloatingIconView properly.
listener.onUpdate(0, true);
animatorSet.playTogether(appAnimator, getBackgroundAnimator(appTargets));
return animatorSet;
}
use of com.android.quickstep.util.MultiValueUpdateListener in project android_packages_apps_Launcher3 by crdroidandroid.
the class QuickstepTransitionManager method getClosingWindowAnimators.
/**
* Animator that controls the transformations of the windows the targets that are closing.
*/
private Animator getClosingWindowAnimators(RemoteAnimationTargetCompat[] appTargets, RemoteAnimationTargetCompat[] wallpaperTargets) {
final int rotationChange = getRotationChange(appTargets);
SurfaceTransactionApplier surfaceApplier = new SurfaceTransactionApplier(mDragLayer);
Matrix matrix = new Matrix();
Point tmpPos = new Point();
Rect tmpRect = new Rect();
ValueAnimator closingAnimator = ValueAnimator.ofFloat(0, 1);
int duration = CLOSING_TRANSITION_DURATION_MS;
float windowCornerRadius = mDeviceProfile.isMultiWindowMode ? 0 : getWindowCornerRadius(mLauncher.getResources());
float startShadowRadius = areAllTargetsTranslucent(appTargets) ? 0 : mMaxShadowRadius;
closingAnimator.setDuration(duration);
closingAnimator.addUpdateListener(new MultiValueUpdateListener() {
FloatProp mDy = new FloatProp(0, mClosingWindowTransY, 0, duration, DEACCEL_1_7);
FloatProp mScale = new FloatProp(1f, 1f, 0, duration, DEACCEL_1_7);
FloatProp mAlpha = new FloatProp(1f, 0f, 25, 125, LINEAR);
FloatProp mShadowRadius = new FloatProp(startShadowRadius, 0, 0, duration, DEACCEL_1_7);
@Override
public void onUpdate(float percent, boolean initOnly) {
SurfaceParams[] params = new SurfaceParams[appTargets.length];
for (int i = appTargets.length - 1; i >= 0; i--) {
RemoteAnimationTargetCompat target = appTargets[i];
SurfaceParams.Builder builder = new SurfaceParams.Builder(target.leash);
if (target.localBounds != null) {
tmpPos.set(target.localBounds.left, target.localBounds.top);
} else {
tmpPos.set(target.position.x, target.position.y);
}
final Rect crop = new Rect(target.screenSpaceBounds);
crop.offsetTo(0, 0);
if (target.mode == MODE_CLOSING) {
tmpRect.set(target.screenSpaceBounds);
if ((rotationChange % 2) != 0) {
final int right = crop.right;
crop.right = crop.bottom;
crop.bottom = right;
}
matrix.setScale(mScale.value, mScale.value, tmpRect.centerX(), tmpRect.centerY());
matrix.postTranslate(0, mDy.value);
matrix.postTranslate(tmpPos.x, tmpPos.y);
builder.withMatrix(matrix).withWindowCrop(crop).withAlpha(mAlpha.value).withCornerRadius(windowCornerRadius).withShadowRadius(mShadowRadius.value);
} else if (target.mode == MODE_OPENING) {
matrix.setTranslate(tmpPos.x, tmpPos.y);
builder.withMatrix(matrix).withWindowCrop(crop).withAlpha(1f);
}
params[i] = builder.build();
}
surfaceApplier.scheduleApply(params);
}
});
return closingAnimator;
}
use of com.android.quickstep.util.MultiValueUpdateListener in project android_packages_apps_Launcher3 by crdroidandroid.
the class QuickstepTransitionManager method getOpeningWindowAnimatorsForWidget.
private Animator getOpeningWindowAnimatorsForWidget(LauncherAppWidgetHostView v, RemoteAnimationTargetCompat[] appTargets, RemoteAnimationTargetCompat[] wallpaperTargets, RemoteAnimationTargetCompat[] nonAppTargets, Rect windowTargetBounds, boolean appTargetsAreTranslucent) {
final RectF widgetBackgroundBounds = new RectF();
final Rect appWindowCrop = new Rect();
final Matrix matrix = new Matrix();
RemoteAnimationTargets openingTargets = new RemoteAnimationTargets(appTargets, wallpaperTargets, nonAppTargets, MODE_OPENING);
RemoteAnimationTargetCompat openingTarget = openingTargets.getFirstAppTarget();
int fallbackBackgroundColor = 0;
if (openingTarget != null && supportsSSplashScreen()) {
fallbackBackgroundColor = mTaskStartParams.containsKey(openingTarget.taskId) ? mTaskStartParams.get(openingTarget.taskId).second : 0;
mTaskStartParams.remove(openingTarget.taskId);
}
if (fallbackBackgroundColor == 0) {
fallbackBackgroundColor = FloatingWidgetView.getDefaultBackgroundColor(mLauncher, openingTarget);
}
final float finalWindowRadius = mDeviceProfile.isMultiWindowMode ? 0 : getWindowCornerRadius(mLauncher.getResources());
final FloatingWidgetView floatingView = FloatingWidgetView.getFloatingWidgetView(mLauncher, v, widgetBackgroundBounds, new Size(windowTargetBounds.width(), windowTargetBounds.height()), finalWindowRadius, appTargetsAreTranslucent, fallbackBackgroundColor);
final float initialWindowRadius = supportsRoundedCornersOnWindows(mLauncher.getResources()) ? floatingView.getInitialCornerRadius() : 0;
SurfaceTransactionApplier surfaceApplier = new SurfaceTransactionApplier(floatingView);
openingTargets.addReleaseCheck(surfaceApplier);
RemoteAnimationTargetCompat navBarTarget = openingTargets.getNavBarRemoteAnimationTarget();
AnimatorSet animatorSet = new AnimatorSet();
ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
appAnimator.setDuration(APP_LAUNCH_DURATION);
appAnimator.setInterpolator(LINEAR);
appAnimator.addListener(floatingView);
appAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
openingTargets.release();
}
});
floatingView.setFastFinishRunnable(animatorSet::end);
appAnimator.addUpdateListener(new MultiValueUpdateListener() {
float mAppWindowScale = 1;
final FloatProp mWidgetForegroundAlpha = new FloatProp(1, /* start */
0, /* end */
0, /* delay */
WIDGET_CROSSFADE_DURATION_MILLIS / 2, /* duration */
LINEAR);
final FloatProp mWidgetFallbackBackgroundAlpha = new FloatProp(0, /* start */
1, /* end */
0, /* delay */
75, /* duration */
LINEAR);
final FloatProp mPreviewAlpha = new FloatProp(0, /* start */
1, /* end */
WIDGET_CROSSFADE_DURATION_MILLIS / 2, /* delay */
WIDGET_CROSSFADE_DURATION_MILLIS / 2, /* duration */
LINEAR);
final FloatProp mWindowRadius = new FloatProp(initialWindowRadius, finalWindowRadius, 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_DURATION, mOpeningXInterpolator);
final FloatProp mDy = new FloatProp(widgetBackgroundBounds.centerY(), windowTargetBounds.centerY(), 0, /* delay */
APP_LAUNCH_DURATION, mOpeningInterpolator);
final FloatProp mWidth = new FloatProp(widgetBackgroundBounds.width(), windowTargetBounds.width(), 0, /* delay */
APP_LAUNCH_DURATION, mOpeningInterpolator);
final FloatProp mHeight = new FloatProp(widgetBackgroundBounds.height(), windowTargetBounds.height(), 0, /* delay */
APP_LAUNCH_DURATION, mOpeningInterpolator);
final FloatProp mNavFadeOut = new FloatProp(1f, 0f, 0, ANIMATION_NAV_FADE_OUT_DURATION, NAV_FADE_OUT_INTERPOLATOR);
final FloatProp mNavFadeIn = new FloatProp(0f, 1f, ANIMATION_DELAY_NAV_FADE_IN, ANIMATION_NAV_FADE_IN_DURATION, NAV_FADE_IN_INTERPOLATOR);
@Override
public void onUpdate(float percent, boolean initOnly) {
widgetBackgroundBounds.set(mDx.value - mWidth.value / 2f, mDy.value - mHeight.value / 2f, mDx.value + mWidth.value / 2f, mDy.value + mHeight.value / 2f);
// Set app window scaling factor to match widget background width
mAppWindowScale = widgetBackgroundBounds.width() / windowTargetBounds.width();
// Crop scaled app window to match widget
appWindowCrop.set(0, /* left */
0, /* top */
Math.round(windowTargetBounds.width()), /* right */
Math.round(widgetBackgroundBounds.height() / mAppWindowScale));
matrix.setTranslate(widgetBackgroundBounds.left, widgetBackgroundBounds.top);
matrix.postScale(mAppWindowScale, mAppWindowScale, widgetBackgroundBounds.left, widgetBackgroundBounds.top);
ArrayList<SurfaceParams> params = new ArrayList<>();
float floatingViewAlpha = appTargetsAreTranslucent ? 1 - mPreviewAlpha.value : 1;
for (int i = appTargets.length - 1; i >= 0; i--) {
RemoteAnimationTargetCompat target = appTargets[i];
SurfaceParams.Builder builder = new SurfaceParams.Builder(target.leash);
if (target.mode == MODE_OPENING) {
floatingView.update(widgetBackgroundBounds, floatingViewAlpha, mWidgetForegroundAlpha.value, mWidgetFallbackBackgroundAlpha.value, mCornerRadiusProgress.value);
builder.withMatrix(matrix).withWindowCrop(appWindowCrop).withAlpha(mPreviewAlpha.value).withCornerRadius(mWindowRadius.value / mAppWindowScale);
}
params.add(builder.build());
}
if (navBarTarget != null) {
final SurfaceParams.Builder navBuilder = new SurfaceParams.Builder(navBarTarget.leash);
if (mNavFadeIn.value > mNavFadeIn.getStartValue()) {
navBuilder.withMatrix(matrix).withWindowCrop(appWindowCrop).withAlpha(mNavFadeIn.value);
} else {
navBuilder.withAlpha(mNavFadeOut.value);
}
params.add(navBuilder.build());
}
surfaceApplier.scheduleApply(params.toArray(new SurfaceParams[params.size()]));
}
});
animatorSet.playTogether(appAnimator, getBackgroundAnimator(appTargets));
return animatorSet;
}
use of com.android.quickstep.util.MultiValueUpdateListener in project android_packages_apps_Launcher3 by crdroidandroid.
the class TaskViewUtils method createRecentsWindowAnimator.
/**
* Creates an animation that controls the window of the opening targets for the recents launch
* animation.
*/
public static void createRecentsWindowAnimator(TaskView v, boolean skipViewChanges, RemoteAnimationTargetCompat[] appTargets, RemoteAnimationTargetCompat[] wallpaperTargets, RemoteAnimationTargetCompat[] nonAppTargets, DepthController depthController, PendingAnimation out, @Nullable TransformParams params, @Nullable TaskViewSimulator tsv) {
boolean isQuickSwitch = v.isEndQuickswitchCuj();
v.setEndQuickswitchCuj(false);
boolean inLiveTileMode = ENABLE_QUICKSTEP_LIVE_TILE.get() && v.getRecentsView().getRunningTaskIndex() != -1;
final RemoteAnimationTargets targets = new RemoteAnimationTargets(appTargets, wallpaperTargets, nonAppTargets, inLiveTileMode ? MODE_CLOSING : MODE_OPENING);
final RemoteAnimationTargetCompat navBarTarget = targets.getNavBarRemoteAnimationTarget();
if (params == null) {
SurfaceTransactionApplier applier = new SurfaceTransactionApplier(v);
targets.addReleaseCheck(applier);
params = new TransformParams().setSyncTransactionApplier(applier).setTargetSet(targets);
}
final RecentsView recentsView = v.getRecentsView();
int taskIndex = recentsView.indexOfChild(v);
Context context = v.getContext();
DeviceProfile dp = BaseActivity.fromContext(context).getDeviceProfile();
boolean showAsGrid = dp.isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get();
boolean parallaxCenterAndAdjacentTask = taskIndex != recentsView.getCurrentPage() && !showAsGrid;
float gridTranslationSecondary = recentsView.getGridTranslationSecondary(taskIndex);
int startScroll = recentsView.getScrollOffset(taskIndex);
TaskViewSimulator topMostSimulator = null;
if (tsv == null && targets.apps.length > 0) {
tsv = new TaskViewSimulator(context, recentsView.getSizeStrategy());
tsv.setDp(dp);
// RecentsView never updates the display rotation until swipe-up so the value may
// be stale. Use the display value instead.
int displayRotation = DisplayController.INSTANCE.get(context).getInfo().rotation;
tsv.getOrientationState().update(displayRotation, displayRotation);
tsv.setPreview(targets.apps[targets.apps.length - 1]);
tsv.fullScreenProgress.value = 0;
tsv.recentsViewScale.value = 1;
if (showAsGrid) {
tsv.taskSecondaryTranslation.value = gridTranslationSecondary;
}
tsv.setScroll(startScroll);
// Fade in the task during the initial 20% of the animation
out.addFloat(params, TransformParams.TARGET_ALPHA, 0, 1, clampToProgress(LINEAR, 0, 0.2f));
}
if (tsv != null) {
out.setFloat(tsv.fullScreenProgress, AnimatedFloat.VALUE, 1, TOUCH_RESPONSE_INTERPOLATOR);
out.setFloat(tsv.recentsViewScale, AnimatedFloat.VALUE, tsv.getFullScreenScale(), TOUCH_RESPONSE_INTERPOLATOR);
if (showAsGrid) {
out.setFloat(tsv.taskSecondaryTranslation, AnimatedFloat.VALUE, 0, TOUCH_RESPONSE_INTERPOLATOR_ACCEL_DEACCEL);
}
out.setFloat(tsv.recentsViewScroll, AnimatedFloat.VALUE, 0, TOUCH_RESPONSE_INTERPOLATOR);
TaskViewSimulator finalTsv = tsv;
TransformParams finalParams = params;
out.addOnFrameCallback(() -> finalTsv.apply(finalParams));
if (navBarTarget != null) {
final Rect cropRect = new Rect();
out.addOnFrameListener(new MultiValueUpdateListener() {
FloatProp mNavFadeOut = new FloatProp(1f, 0f, 0, ANIMATION_NAV_FADE_OUT_DURATION, NAV_FADE_OUT_INTERPOLATOR);
FloatProp mNavFadeIn = new FloatProp(0f, 1f, ANIMATION_DELAY_NAV_FADE_IN, ANIMATION_NAV_FADE_IN_DURATION, NAV_FADE_IN_INTERPOLATOR);
@Override
public void onUpdate(float percent, boolean initOnly) {
final SurfaceParams.Builder navBuilder = new SurfaceParams.Builder(navBarTarget.leash);
if (mNavFadeIn.value > mNavFadeIn.getStartValue()) {
finalTsv.getCurrentCropRect().round(cropRect);
navBuilder.withMatrix(finalTsv.getCurrentMatrix()).withWindowCrop(cropRect).withAlpha(mNavFadeIn.value);
} else {
navBuilder.withAlpha(mNavFadeOut.value);
}
finalParams.applySurfaceParams(navBuilder.build());
}
});
} else if (inLiveTileMode) {
// There is no transition animation for app launch from recent in live tile mode so
// we have to trigger the navigation bar animation from system here.
final RecentsAnimationController controller = recentsView.getRecentsAnimationController();
if (controller != null) {
controller.animateNavigationBarToApp(RECENTS_LAUNCH_DURATION);
}
}
topMostSimulator = tsv;
}
if (!skipViewChanges && parallaxCenterAndAdjacentTask && topMostSimulator != null) {
out.addFloat(v, VIEW_ALPHA, 1, 0, clampToProgress(LINEAR, 0.2f, 0.4f));
TaskViewSimulator simulatorToCopy = topMostSimulator;
simulatorToCopy.apply(params);
// Mt represents the overall transformation on the thumbnailView relative to the
// Launcher's rootView
// K(t) represents transformation on the running window by the taskViewSimulator at
// any time t.
// at t = 0, we know that the simulator matches the thumbnailView. So if we apply K(0)`
// on the Launcher's rootView, the thumbnailView would match the full running task
// window. If we apply "K(0)` K(t)" thumbnailView will match the final transformed
// window at any time t. This gives the overall matrix on thumbnailView to be:
// Mt K(0)` K(t)
// During animation we apply transformation on the thumbnailView (and not the rootView)
// to follow the TaskViewSimulator. So the final matrix applied on the thumbnailView is:
// Mt K(0)` K(t) Mt`
TaskThumbnailView ttv = v.getThumbnail();
RectF tvBounds = new RectF(0, 0, ttv.getWidth(), ttv.getHeight());
float[] tvBoundsMapped = new float[] { 0, 0, ttv.getWidth(), ttv.getHeight() };
getDescendantCoordRelativeToAncestor(ttv, ttv.getRootView(), tvBoundsMapped, false);
RectF tvBoundsInRoot = new RectF(tvBoundsMapped[0], tvBoundsMapped[1], tvBoundsMapped[2], tvBoundsMapped[3]);
Matrix mt = new Matrix();
mt.setRectToRect(tvBounds, tvBoundsInRoot, ScaleToFit.FILL);
Matrix mti = new Matrix();
mt.invert(mti);
Matrix k0i = new Matrix();
simulatorToCopy.getCurrentMatrix().invert(k0i);
Matrix animationMatrix = new Matrix();
out.addOnFrameCallback(() -> {
animationMatrix.set(mt);
animationMatrix.postConcat(k0i);
animationMatrix.postConcat(simulatorToCopy.getCurrentMatrix());
animationMatrix.postConcat(mti);
ttv.setAnimationMatrix(animationMatrix);
});
out.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
ttv.setAnimationMatrix(null);
}
});
}
out.addListener(new AnimationSuccessListener() {
@Override
public void onAnimationSuccess(Animator animator) {
if (isQuickSwitch) {
InteractionJankMonitorWrapper.end(InteractionJankMonitorWrapper.CUJ_QUICK_SWITCH);
}
}
@Override
public void onAnimationEnd(Animator animation) {
targets.release();
super.onAnimationEnd(animation);
}
});
if (depthController != null) {
out.setFloat(depthController, DEPTH, BACKGROUND_APP.getDepth(context), TOUCH_RESPONSE_INTERPOLATOR);
}
}
use of com.android.quickstep.util.MultiValueUpdateListener in project android_packages_apps_Launcher3 by crdroidandroid.
the class AllAppsEduView method playAnimation.
private void playAnimation() {
if (mAnimation != null) {
return;
}
mAnimation = new AnimatorSet();
final Rect circleBoundsOg = new Rect(mCircle.getBounds());
final Rect gradientBoundsOg = new Rect(mGradient.getBounds());
final Rect temp = new Rect();
final float transY = mMaxHeightPx - mCircleSizePx - mPaddingPx;
// 1st: Circle alpha/scale
int firstPart = 600;
// 2nd: Circle animates upwards, Gradient alpha fades in, Gradient grows, All Apps hint
int secondPart = 1200;
int introDuration = firstPart + secondPart;
AnimatorPlaybackController stateAnimationController = mTouchController.initAllAppsAnimation();
float maxAllAppsProgress = 0.75f;
ValueAnimator intro = ValueAnimator.ofFloat(0, 1f);
intro.setInterpolator(LINEAR);
intro.setDuration(introDuration);
intro.addUpdateListener((new MultiValueUpdateListener() {
FloatProp mCircleAlpha = new FloatProp(0, 255, 0, firstPart, LINEAR);
FloatProp mCircleScale = new FloatProp(2f, 1f, 0, firstPart, OVERSHOOT_1_7);
FloatProp mDeltaY = new FloatProp(0, transY, firstPart, secondPart, FAST_OUT_SLOW_IN);
FloatProp mGradientAlpha = new FloatProp(0, 255, firstPart, secondPart * 0.3f, LINEAR);
@Override
public void onUpdate(float progress, boolean initOnly) {
temp.set(circleBoundsOg);
temp.offset(0, (int) -mDeltaY.value);
Utilities.scaleRectAboutCenter(temp, mCircleScale.value);
mCircle.setBounds(temp);
mCircle.setAlpha((int) mCircleAlpha.value);
mGradient.setAlpha((int) mGradientAlpha.value);
temp.set(gradientBoundsOg);
temp.top -= mDeltaY.value;
mGradient.setBounds(temp);
invalidate();
float stateProgress = Utilities.mapToRange(mDeltaY.value, 0, transY, 0, maxAllAppsProgress, LINEAR);
stateAnimationController.setPlayFraction(stateProgress);
}
}));
intro.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mCircle.setAlpha(0);
mGradient.setAlpha(0);
}
});
mLauncher.getAppsView().setVisibility(View.VISIBLE);
mAnimation.play(intro);
ValueAnimator closeAllApps = ValueAnimator.ofFloat(maxAllAppsProgress, 0f);
closeAllApps.addUpdateListener(valueAnimator -> {
stateAnimationController.setPlayFraction((float) valueAnimator.getAnimatedValue());
});
closeAllApps.setInterpolator(FAST_OUT_SLOW_IN);
closeAllApps.setStartDelay(introDuration);
closeAllApps.setDuration(250);
mAnimation.play(closeAllApps);
mAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mAnimation = null;
// Handles cancelling the animation used to hint towards All Apps.
mLauncher.getStateManager().goToState(NORMAL, false);
handleClose(false);
}
});
mAnimation.start();
}
Aggregations