use of com.android.launcher3.util.PendingAnimation in project android_packages_apps_Launcher3 by AOSPA.
the class RecentsView method createTaskLaunchAnimation.
public PendingAnimation createTaskLaunchAnimation(TaskView tv, long duration, Interpolator interpolator) {
if (FeatureFlags.IS_STUDIO_BUILD && mPendingAnimation != null) {
throw new IllegalStateException("Another pending animation is still running");
}
int count = getTaskViewCount();
if (count == 0) {
return new PendingAnimation(duration);
}
// When swiping down from overview to tasks, ensures the snapped page's scroll maintain
// invariant between quick switch and overview, to ensure a smooth animation transition.
updateGridProperties();
updateScrollSynchronously();
int targetSysUiFlags = tv.getThumbnail().getSysUiStatusNavFlags();
final boolean[] passedOverviewThreshold = new boolean[] { false };
ValueAnimator progressAnim = ValueAnimator.ofFloat(0, 1);
progressAnim.addUpdateListener(animator -> {
// tasks' flags
if (animator.getAnimatedFraction() > UPDATE_SYSUI_FLAGS_THRESHOLD) {
mActivity.getSystemUiController().updateUiState(UI_STATE_FULLSCREEN_TASK, targetSysUiFlags);
} else {
mActivity.getSystemUiController().updateUiState(UI_STATE_FULLSCREEN_TASK, 0);
}
// Passing the threshold from taskview to fullscreen app will vibrate
final boolean passed = animator.getAnimatedFraction() >= SUCCESS_TRANSITION_PROGRESS;
if (passed != passedOverviewThreshold[0]) {
passedOverviewThreshold[0] = passed;
performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
}
});
AnimatorSet anim = createAdjacentPageAnimForTaskLaunch(tv);
DepthController depthController = getDepthController();
if (depthController != null) {
ObjectAnimator depthAnimator = ObjectAnimator.ofFloat(depthController, DEPTH, BACKGROUND_APP.getDepth(mActivity));
anim.play(depthAnimator);
}
anim.play(progressAnim);
anim.setInterpolator(interpolator);
mPendingAnimation = new PendingAnimation(duration);
mPendingAnimation.add(anim);
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator().addOverviewToAppAnim(mPendingAnimation, interpolator));
mPendingAnimation.addOnFrameCallback(this::redrawLiveTile);
}
mPendingAnimation.addEndListener(isSuccess -> {
if (isSuccess) {
if (tv.getTaskIds()[1] != -1) {
// TODO(b/194414938): make this part of the animations instead.
TaskViewUtils.setSplitAuxiliarySurfacesShown(mRemoteTargetHandles[0].getTransformParams().getTargetSet().nonApps, true, /*shown*/
false);
}
if (ENABLE_QUICKSTEP_LIVE_TILE.get() && tv.isRunningTask()) {
finishRecentsAnimation(false, /* toRecents */
null);
onTaskLaunchAnimationEnd(true);
} else {
tv.launchTask(this::onTaskLaunchAnimationEnd);
}
Task task = tv.getTask();
if (task != null) {
mActivity.getStatsLogManager().logger().withItemInfo(tv.getItemInfo()).log(LAUNCHER_TASK_LAUNCH_SWIPE_DOWN);
}
} else {
onTaskLaunchAnimationEnd(false);
}
mPendingAnimation = null;
});
return mPendingAnimation;
}
use of com.android.launcher3.util.PendingAnimation in project android_packages_apps_Launcher3 by AOSPA.
the class RecentsView method createAllTasksDismissAnimation.
public PendingAnimation createAllTasksDismissAnimation(long duration) {
if (FeatureFlags.IS_STUDIO_BUILD && mPendingAnimation != null) {
throw new IllegalStateException("Another pending animation is still running");
}
PendingAnimation anim = new PendingAnimation(duration);
int count = getTaskViewCount();
for (int i = 0; i < count; i++) {
addDismissedTaskAnimations(requireTaskViewAt(i), duration, anim);
}
mPendingAnimation = anim;
mPendingAnimation.addEndListener(isSuccess -> {
if (isSuccess) {
// Remove all the task views now
finishRecentsAnimation(true, /* toRecents */
false, /* shouldPip */
() -> {
UI_HELPER_EXECUTOR.getHandler().postDelayed(ActivityManagerWrapper.getInstance()::removeAllRecentTasks, REMOVE_TASK_WAIT_FOR_APP_STOP_MS);
removeTasksViewsAndClearAllButton();
startHome();
});
}
mPendingAnimation = null;
});
return anim;
}
use of com.android.launcher3.util.PendingAnimation in project android_packages_apps_Launcher3 by AOSPA.
the class FloatingTaskView method addAnimation.
public void addAnimation(PendingAnimation animation, RectF startingBounds, Rect endBounds, View viewToCover, boolean fadeWithThumbnail) {
final BaseDragLayer dragLayer = mActivity.getDragLayer();
int[] dragLayerBounds = new int[2];
dragLayer.getLocationOnScreen(dragLayerBounds);
SplitOverlayProperties prop = new SplitOverlayProperties(endBounds, startingBounds, viewToCover, dragLayerBounds[0], dragLayerBounds[1]);
ValueAnimator transitionAnimator = ValueAnimator.ofFloat(0, 1);
animation.add(transitionAnimator);
long animDuration = animation.getDuration();
Rect crop = new Rect();
RectF floatingTaskViewBounds = new RectF();
final float initialWindowRadius = supportsRoundedCornersOnWindows(getResources()) ? Math.max(crop.width(), crop.height()) / 2f : 0f;
if (fadeWithThumbnail) {
animation.addFloat(mSplitPlaceholderView, SplitPlaceholderView.ALPHA_FLOAT, 0, 1, ACCEL);
animation.addFloat(mImageView, LauncherAnimUtils.VIEW_ALPHA, 1, 0, DEACCEL_3);
}
MultiValueUpdateListener listener = new MultiValueUpdateListener() {
final FloatProp mWindowRadius = new FloatProp(initialWindowRadius, initialWindowRadius, 0, animDuration, LINEAR);
final FloatProp mDx = new FloatProp(0, prop.dX, 0, animDuration, LINEAR);
final FloatProp mDy = new FloatProp(0, prop.dY, 0, animDuration, LINEAR);
final FloatProp mTaskViewScaleX = new FloatProp(prop.initialTaskViewScaleX, prop.finalTaskViewScaleX, 0, animDuration, LINEAR);
final FloatProp mTaskViewScaleY = new FloatProp(prop.initialTaskViewScaleY, prop.finalTaskViewScaleY, 0, animDuration, LINEAR);
@Override
public void onUpdate(float percent, boolean initOnly) {
// Calculate the icon position.
floatingTaskViewBounds.set(startingBounds);
floatingTaskViewBounds.offset(mDx.value, mDy.value);
Utilities.scaleRectFAboutCenter(floatingTaskViewBounds, mTaskViewScaleX.value, mTaskViewScaleY.value);
update(floatingTaskViewBounds, percent, mWindowRadius.value * 1);
}
};
transitionAnimator.addUpdateListener(listener);
}
use of com.android.launcher3.util.PendingAnimation in project android_packages_apps_Launcher3 by AOSPA.
the class AnimatorControllerWithResistance method createRecentsResistanceAnim.
/**
* Creates the resistance animation for {@link #createForRecents}, or can be used separately
* when starting from recents, i.e. {@link #createRecentsResistanceFromOverviewAnim}.
*/
public static <SCALE, TRANSLATION> PendingAnimation createRecentsResistanceAnim(RecentsParams<SCALE, TRANSLATION> params) {
Rect startRect = new Rect();
PagedOrientationHandler orientationHandler = params.recentsOrientedState.getOrientationHandler();
LauncherActivityInterface.INSTANCE.calculateTaskSize(params.context, params.dp, startRect);
long distanceToCover = startRect.bottom;
PendingAnimation resistAnim = params.resistAnim != null ? params.resistAnim : new PendingAnimation(distanceToCover * 2);
PointF pivot = new PointF();
float fullscreenScale = params.recentsOrientedState.getFullScreenScaleAndPivot(startRect, params.dp, pivot);
// Compute where the task view would be based on the end scale.
RectF endRectF = new RectF(startRect);
Matrix temp = new Matrix();
temp.setScale(params.resistanceParams.scaleMaxResist, params.resistanceParams.scaleMaxResist, pivot.x, pivot.y);
temp.mapRect(endRectF);
// Translate such that the task view touches the top of the screen when drag does.
float endTranslation = endRectF.top * orientationHandler.getSecondaryTranslationDirectionFactor() * params.resistanceParams.translationFactor;
resistAnim.addFloat(params.translationTarget, params.translationProperty, params.startTranslation, endTranslation, RECENTS_TRANSLATE_RESIST_INTERPOLATOR);
float prevScaleRate = (fullscreenScale - params.startScale) / (params.dp.heightPx - startRect.bottom);
// This is what the scale would be at the end of the drag if we didn't apply resistance.
float endScale = params.startScale - prevScaleRate * distanceToCover;
// Create an interpolator that resists the scale so the scale doesn't get smaller than
// RECENTS_SCALE_MAX_RESIST.
float startResist = Utilities.getProgress(params.resistanceParams.scaleStartResist, params.startScale, endScale);
float maxResist = Utilities.getProgress(params.resistanceParams.scaleMaxResist, params.startScale, endScale);
float stopResist = params.resistanceParams.stopScalingAtTop ? 1f - startRect.top / endRectF.top : 1f;
final TimeInterpolator scaleInterpolator = t -> {
if (t < startResist) {
return t;
}
if (t > stopResist) {
return maxResist;
}
float resistProgress = Utilities.getProgress(t, startResist, stopResist);
resistProgress = RECENTS_SCALE_RESIST_INTERPOLATOR.getInterpolation(resistProgress);
return startResist + resistProgress * (maxResist - startResist);
};
resistAnim.addFloat(params.scaleTarget, params.scaleProperty, params.startScale, endScale, scaleInterpolator);
return resistAnim;
}
use of com.android.launcher3.util.PendingAnimation in project android_packages_apps_Launcher3 by AOSPA.
the class TaskViewUtils method createRecentsWindowAnimator.
public static void createRecentsWindowAnimator(@NonNull TaskView v, boolean skipViewChanges, @NonNull RemoteAnimationTargetCompat[] appTargets, @NonNull RemoteAnimationTargetCompat[] wallpaperTargets, @NonNull RemoteAnimationTargetCompat[] nonAppTargets, @Nullable DepthController depthController, PendingAnimation out) {
RecentsView recentsView = v.getRecentsView();
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();
SurfaceTransactionApplier applier = new SurfaceTransactionApplier(v);
targets.addReleaseCheck(applier);
RemoteTargetHandle[] remoteTargetHandles;
RemoteTargetHandle[] recentsViewHandles = recentsView.getRemoteTargetHandles();
if (v.isRunningTask() && recentsViewHandles != null) {
// Re-use existing handles
remoteTargetHandles = recentsViewHandles;
} else {
RemoteTargetGluer gluer = new RemoteTargetGluer(v.getContext(), recentsView.getSizeStrategy(), targets);
if (v.containsMultipleTasks()) {
remoteTargetHandles = gluer.assignTargetsForSplitScreen(targets, v.getTaskIds());
} else {
remoteTargetHandles = gluer.assignTargets(targets);
}
}
for (RemoteTargetHandle remoteTargetGluer : remoteTargetHandles) {
remoteTargetGluer.getTransformParams().setSyncTransactionApplier(applier);
}
int taskIndex = recentsView.indexOfChild(v);
Context context = v.getContext();
DeviceProfile dp = BaseActivity.fromContext(context).getDeviceProfile();
boolean showAsGrid = dp.overviewShowAsGrid;
boolean parallaxCenterAndAdjacentTask = taskIndex != recentsView.getCurrentPage() && !showAsGrid;
int taskRectTranslationPrimary = recentsView.getScrollOffset(taskIndex);
int taskRectTranslationSecondary = showAsGrid ? (int) v.getGridTranslationY() : 0;
RemoteTargetHandle[] topMostSimulators = null;
if (!v.isRunningTask()) {
// TVSs already initialized from the running task, no need to re-init
for (RemoteTargetHandle targetHandle : remoteTargetHandles) {
TaskViewSimulator tvsLocal = targetHandle.getTaskViewSimulator();
tvsLocal.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;
tvsLocal.getOrientationState().update(displayRotation, displayRotation);
tvsLocal.fullScreenProgress.value = 0;
tvsLocal.recentsViewScale.value = 1;
tvsLocal.setIsGridTask(v.isGridTask());
tvsLocal.getOrientationState().getOrientationHandler().set(tvsLocal, TaskViewSimulator::setTaskRectTranslation, taskRectTranslationPrimary, taskRectTranslationSecondary);
// Fade in the task during the initial 20% of the animation
out.addFloat(targetHandle.getTransformParams(), TransformParams.TARGET_ALPHA, 0, 1, clampToProgress(LINEAR, 0, 0.2f));
}
}
for (RemoteTargetHandle targetHandle : remoteTargetHandles) {
TaskViewSimulator tvsLocal = targetHandle.getTaskViewSimulator();
out.setFloat(tvsLocal.fullScreenProgress, AnimatedFloat.VALUE, 1, TOUCH_RESPONSE_INTERPOLATOR);
out.setFloat(tvsLocal.recentsViewScale, AnimatedFloat.VALUE, tvsLocal.getFullScreenScale(), TOUCH_RESPONSE_INTERPOLATOR);
out.setFloat(tvsLocal.recentsViewScroll, AnimatedFloat.VALUE, 0, TOUCH_RESPONSE_INTERPOLATOR);
out.addOnFrameCallback(() -> {
for (RemoteTargetHandle handle : remoteTargetHandles) {
handle.getTaskViewSimulator().apply(handle.getTransformParams());
}
});
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);
// TODO Do we need to operate over multiple TVSs for the navbar leash?
for (RemoteTargetHandle handle : remoteTargetHandles) {
if (mNavFadeIn.value > mNavFadeIn.getStartValue()) {
TaskViewSimulator taskViewSimulator = handle.getTaskViewSimulator();
taskViewSimulator.getCurrentCropRect().round(cropRect);
navBuilder.withMatrix(taskViewSimulator.getCurrentMatrix()).withWindowCrop(cropRect).withAlpha(mNavFadeIn.value);
} else {
navBuilder.withAlpha(mNavFadeOut.value);
}
handle.getTransformParams().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);
}
}
topMostSimulators = remoteTargetHandles;
}
if (!skipViewChanges && parallaxCenterAndAdjacentTask && topMostSimulators.length > 0) {
out.addFloat(v, VIEW_ALPHA, 1, 0, clampToProgress(LINEAR, 0.2f, 0.4f));
RemoteTargetHandle[] simulatorCopies = topMostSimulators;
for (RemoteTargetHandle handle : simulatorCopies) {
handle.getTaskViewSimulator().apply(handle.getTransformParams());
}
// 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[] thumbnails = v.getThumbnails();
Matrix[] mt = new Matrix[simulatorCopies.length];
Matrix[] mti = new Matrix[simulatorCopies.length];
for (int i = 0; i < thumbnails.length; i++) {
TaskThumbnailView ttv = thumbnails[i];
RectF localBounds = 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 localBoundsInRoot = new RectF(tvBoundsMapped[0], tvBoundsMapped[1], tvBoundsMapped[2], tvBoundsMapped[3]);
Matrix localMt = new Matrix();
localMt.setRectToRect(localBounds, localBoundsInRoot, ScaleToFit.FILL);
mt[i] = localMt;
Matrix localMti = new Matrix();
localMt.invert(localMti);
mti[i] = localMti;
}
Matrix[] k0i = new Matrix[simulatorCopies.length];
for (int i = 0; i < simulatorCopies.length; i++) {
k0i[i] = new Matrix();
simulatorCopies[i].getTaskViewSimulator().getCurrentMatrix().invert(k0i[i]);
}
Matrix animationMatrix = new Matrix();
out.addOnFrameCallback(() -> {
for (int i = 0; i < simulatorCopies.length; i++) {
animationMatrix.set(mt[i]);
animationMatrix.postConcat(k0i[i]);
animationMatrix.postConcat(simulatorCopies[i].getTaskViewSimulator().getCurrentMatrix());
animationMatrix.postConcat(mti[i]);
thumbnails[i].setAnimationMatrix(animationMatrix);
}
});
out.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
for (TaskThumbnailView ttv : thumbnails) {
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);
}
}
Aggregations