Loading go/quickstep/src/com/android/launcher3/GoLauncherAppTransitionManagerImpl.java +41 −1 Original line number Diff line number Diff line package com.android.launcher3; import static com.android.launcher3.Utilities.postAsyncCallback; import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.quickstep.TaskUtils.taskIsATargetWithMode; import static com.android.quickstep.views.IconRecentsView.CONTENT_ALPHA; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.app.ActivityOptions; import android.content.Context; import android.os.Handler; import android.view.View; import com.android.quickstep.views.IconRecentsView; import com.android.systemui.shared.system.RemoteAnimationRunnerCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; /** Loading @@ -28,6 +32,12 @@ public final class GoLauncherAppTransitionManagerImpl extends QuickstepAppTransi return mLauncher.getStateManager().getState().overviewUi; } @Override RemoteAnimationRunnerCompat getWallpaperOpenRunner(boolean fromUnlock) { return new GoWallpaperOpenLauncherAnimationRunner(mHandler, false /* startAtFrontOfQueue */, fromUnlock); } @Override protected void composeRecentsLaunchAnimator(AnimatorSet anim, View v, RemoteAnimationTargetCompat[] targets, boolean launcherClosing) { Loading @@ -51,4 +61,34 @@ public final class GoLauncherAppTransitionManagerImpl extends QuickstepAppTransi return mLauncher.getStateManager()::reapplyState; } /** * Remote animation runner for animation from app to Launcher. For Go, when going to recents, * we need to ensure that the recents view is ready for remote animation before starting. */ private final class GoWallpaperOpenLauncherAnimationRunner extends WallpaperOpenLauncherAnimationRunner { public GoWallpaperOpenLauncherAnimationRunner(Handler handler, boolean startAtFrontOfQueue, boolean fromUnlock) { super(handler, startAtFrontOfQueue, fromUnlock); } @Override public void onCreateAnimation(RemoteAnimationTargetCompat[] targetCompats, AnimationResult result) { boolean isGoingToRecents = taskIsATargetWithMode(targetCompats, mLauncher.getTaskId(), MODE_OPENING) && (mLauncher.getStateManager().getState() == LauncherState.OVERVIEW); if (isGoingToRecents) { IconRecentsView recentsView = mLauncher.getOverviewPanel(); if (!recentsView.isReadyForRemoteAnim()) { recentsView.setOnReadyForRemoteAnimCallback(() -> postAsyncCallback(mHandler, () -> onCreateAnimation(targetCompats, result)) ); return; } } super.onCreateAnimation(targetCompats, result); } } } go/quickstep/src/com/android/quickstep/views/IconRecentsView.java +38 −0 Original line number Diff line number Diff line Loading @@ -378,6 +378,36 @@ public final class IconRecentsView extends FrameLayout implements Insettable { return view.getThumbnailView(); } /** * Whether this view has processed all data changes and is ready to animate from the app to * the overview. * * @return true if ready to animate app to overview, false otherwise */ public boolean isReadyForRemoteAnim() { return !mTaskRecyclerView.hasPendingAdapterUpdates(); } /** * Set a callback for whenever this view is ready to do a remote animation from the app to * overview. See {@link #isReadyForRemoteAnim()}. * * @param callback callback to run when view is ready to animate */ public void setOnReadyForRemoteAnimCallback(onReadyForRemoteAnimCallback callback) { mTaskRecyclerView.getViewTreeObserver().addOnGlobalLayoutListener( new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { if (isReadyForRemoteAnim()) { callback.onReadyForRemoteAnim(); mTaskRecyclerView.getViewTreeObserver(). removeOnGlobalLayoutListener(this); } } }); } /** * Clear all tasks and animate out. */ Loading Loading @@ -557,4 +587,12 @@ public final class IconRecentsView extends FrameLayout implements Insettable { mTaskRecyclerView.setPadding(insets.left, insets.top, insets.right, insets.bottom); mTaskRecyclerView.invalidateItemDecorations(); } /** * Callback for when this view is ready for a remote animation from app to overview. */ public interface onReadyForRemoteAnimCallback { void onReadyForRemoteAnim(); } } quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java +79 −65 Original line number Diff line number Diff line Loading @@ -132,7 +132,7 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans private final DragLayer mDragLayer; private final AlphaProperty mDragLayerAlpha; private final Handler mHandler; final Handler mHandler; private final boolean mIsRtl; private final float mContentTransY; Loading Loading @@ -573,70 +573,9 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans * @return Runner that plays when user goes to Launcher * ie. pressing home, swiping up from nav bar. */ private RemoteAnimationRunnerCompat getWallpaperOpenRunner(boolean fromUnlock) { return new LauncherAnimationRunner(mHandler, false /* startAtFrontOfQueue */) { @Override public void onCreateAnimation(RemoteAnimationTargetCompat[] targetCompats, AnimationResult result) { if (!mLauncher.hasBeenResumed()) { // If launcher is not resumed, wait until new async-frame after resume mLauncher.setOnResumeCallback(() -> postAsyncCallback(mHandler, () -> onCreateAnimation(targetCompats, result))); return; } if (mLauncher.hasSomeInvisibleFlag(PENDING_INVISIBLE_BY_WALLPAPER_ANIMATION)) { mLauncher.addForceInvisibleFlag(INVISIBLE_BY_PENDING_FLAGS); mLauncher.getStateManager().moveToRestState(); } AnimatorSet anim = null; RemoteAnimationProvider provider = mRemoteAnimationProvider; if (provider != null) { anim = provider.createWindowAnimation(targetCompats); } if (anim == null) { anim = new AnimatorSet(); anim.play(fromUnlock ? getUnlockWindowAnimator(targetCompats) : getClosingWindowAnimators(targetCompats)); // 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 // contents of launcher unless we know that we are animating home as a result // of the home button press with quickstep, which will result in launcher being // started on touch down, prior to the animation home (and won't be in the // 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(targetCompats, MODE_OPENING) || mLauncher.isForceInvisible()) { // Only register the content animation for cancellation when state changes mLauncher.getStateManager().setCurrentAnimation(anim); if (fromUnlock) { Pair<AnimatorSet, Runnable> contentAnimator = getLauncherContentAnimator(false /* isAppOpening */, new float[] {mContentTransY, 0}); contentAnimator.first.setStartDelay(0); anim.play(contentAnimator.first); anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { contentAnimator.second.run(); } }); } else { createLauncherResumeAnimation(anim); } } } mLauncher.clearForceInvisibleFlag(INVISIBLE_ALL); result.setAnimation(anim); } }; RemoteAnimationRunnerCompat getWallpaperOpenRunner(boolean fromUnlock) { return new WallpaperOpenLauncherAnimationRunner(mHandler, false /* startAtFrontOfQueue */, fromUnlock); } /** Loading Loading @@ -773,4 +712,79 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans return mLauncher.checkSelfPermission(CONTROL_REMOTE_APP_TRANSITION_PERMISSION) == PackageManager.PERMISSION_GRANTED; } /** * Remote animation runner for animation from the app to Launcher, including recents. */ class WallpaperOpenLauncherAnimationRunner extends LauncherAnimationRunner { private final boolean mFromUnlock; public WallpaperOpenLauncherAnimationRunner(Handler handler, boolean startAtFrontOfQueue, boolean fromUnlock) { super(handler, startAtFrontOfQueue); mFromUnlock = fromUnlock; } @Override public void onCreateAnimation(RemoteAnimationTargetCompat[] targetCompats, LauncherAnimationRunner.AnimationResult result) { if (!mLauncher.hasBeenResumed()) { // If launcher is not resumed, wait until new async-frame after resume mLauncher.setOnResumeCallback(() -> postAsyncCallback(mHandler, () -> onCreateAnimation(targetCompats, result))); return; } if (mLauncher.hasSomeInvisibleFlag(PENDING_INVISIBLE_BY_WALLPAPER_ANIMATION)) { mLauncher.addForceInvisibleFlag(INVISIBLE_BY_PENDING_FLAGS); mLauncher.getStateManager().moveToRestState(); } AnimatorSet anim = null; RemoteAnimationProvider provider = mRemoteAnimationProvider; if (provider != null) { anim = provider.createWindowAnimation(targetCompats); } if (anim == null) { anim = new AnimatorSet(); anim.play(mFromUnlock ? getUnlockWindowAnimator(targetCompats) : getClosingWindowAnimators(targetCompats)); // 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 // contents of launcher unless we know that we are animating home as a result // of the home button press with quickstep, which will result in launcher being // started on touch down, prior to the animation home (and won't be in the // 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(targetCompats, MODE_OPENING) || mLauncher.isForceInvisible()) { // Only register the content animation for cancellation when state changes mLauncher.getStateManager().setCurrentAnimation(anim); if (mFromUnlock) { Pair<AnimatorSet, Runnable> contentAnimator = getLauncherContentAnimator(false /* isAppOpening */, new float[] {mContentTransY, 0}); contentAnimator.first.setStartDelay(0); anim.play(contentAnimator.first); anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { contentAnimator.second.run(); } }); } else { createLauncherResumeAnimation(anim); } } } mLauncher.clearForceInvisibleFlag(INVISIBLE_ALL); result.setAnimation(anim); } } } Loading
go/quickstep/src/com/android/launcher3/GoLauncherAppTransitionManagerImpl.java +41 −1 Original line number Diff line number Diff line package com.android.launcher3; import static com.android.launcher3.Utilities.postAsyncCallback; import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.quickstep.TaskUtils.taskIsATargetWithMode; import static com.android.quickstep.views.IconRecentsView.CONTENT_ALPHA; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.app.ActivityOptions; import android.content.Context; import android.os.Handler; import android.view.View; import com.android.quickstep.views.IconRecentsView; import com.android.systemui.shared.system.RemoteAnimationRunnerCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; /** Loading @@ -28,6 +32,12 @@ public final class GoLauncherAppTransitionManagerImpl extends QuickstepAppTransi return mLauncher.getStateManager().getState().overviewUi; } @Override RemoteAnimationRunnerCompat getWallpaperOpenRunner(boolean fromUnlock) { return new GoWallpaperOpenLauncherAnimationRunner(mHandler, false /* startAtFrontOfQueue */, fromUnlock); } @Override protected void composeRecentsLaunchAnimator(AnimatorSet anim, View v, RemoteAnimationTargetCompat[] targets, boolean launcherClosing) { Loading @@ -51,4 +61,34 @@ public final class GoLauncherAppTransitionManagerImpl extends QuickstepAppTransi return mLauncher.getStateManager()::reapplyState; } /** * Remote animation runner for animation from app to Launcher. For Go, when going to recents, * we need to ensure that the recents view is ready for remote animation before starting. */ private final class GoWallpaperOpenLauncherAnimationRunner extends WallpaperOpenLauncherAnimationRunner { public GoWallpaperOpenLauncherAnimationRunner(Handler handler, boolean startAtFrontOfQueue, boolean fromUnlock) { super(handler, startAtFrontOfQueue, fromUnlock); } @Override public void onCreateAnimation(RemoteAnimationTargetCompat[] targetCompats, AnimationResult result) { boolean isGoingToRecents = taskIsATargetWithMode(targetCompats, mLauncher.getTaskId(), MODE_OPENING) && (mLauncher.getStateManager().getState() == LauncherState.OVERVIEW); if (isGoingToRecents) { IconRecentsView recentsView = mLauncher.getOverviewPanel(); if (!recentsView.isReadyForRemoteAnim()) { recentsView.setOnReadyForRemoteAnimCallback(() -> postAsyncCallback(mHandler, () -> onCreateAnimation(targetCompats, result)) ); return; } } super.onCreateAnimation(targetCompats, result); } } }
go/quickstep/src/com/android/quickstep/views/IconRecentsView.java +38 −0 Original line number Diff line number Diff line Loading @@ -378,6 +378,36 @@ public final class IconRecentsView extends FrameLayout implements Insettable { return view.getThumbnailView(); } /** * Whether this view has processed all data changes and is ready to animate from the app to * the overview. * * @return true if ready to animate app to overview, false otherwise */ public boolean isReadyForRemoteAnim() { return !mTaskRecyclerView.hasPendingAdapterUpdates(); } /** * Set a callback for whenever this view is ready to do a remote animation from the app to * overview. See {@link #isReadyForRemoteAnim()}. * * @param callback callback to run when view is ready to animate */ public void setOnReadyForRemoteAnimCallback(onReadyForRemoteAnimCallback callback) { mTaskRecyclerView.getViewTreeObserver().addOnGlobalLayoutListener( new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { if (isReadyForRemoteAnim()) { callback.onReadyForRemoteAnim(); mTaskRecyclerView.getViewTreeObserver(). removeOnGlobalLayoutListener(this); } } }); } /** * Clear all tasks and animate out. */ Loading Loading @@ -557,4 +587,12 @@ public final class IconRecentsView extends FrameLayout implements Insettable { mTaskRecyclerView.setPadding(insets.left, insets.top, insets.right, insets.bottom); mTaskRecyclerView.invalidateItemDecorations(); } /** * Callback for when this view is ready for a remote animation from app to overview. */ public interface onReadyForRemoteAnimCallback { void onReadyForRemoteAnim(); } }
quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java +79 −65 Original line number Diff line number Diff line Loading @@ -132,7 +132,7 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans private final DragLayer mDragLayer; private final AlphaProperty mDragLayerAlpha; private final Handler mHandler; final Handler mHandler; private final boolean mIsRtl; private final float mContentTransY; Loading Loading @@ -573,70 +573,9 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans * @return Runner that plays when user goes to Launcher * ie. pressing home, swiping up from nav bar. */ private RemoteAnimationRunnerCompat getWallpaperOpenRunner(boolean fromUnlock) { return new LauncherAnimationRunner(mHandler, false /* startAtFrontOfQueue */) { @Override public void onCreateAnimation(RemoteAnimationTargetCompat[] targetCompats, AnimationResult result) { if (!mLauncher.hasBeenResumed()) { // If launcher is not resumed, wait until new async-frame after resume mLauncher.setOnResumeCallback(() -> postAsyncCallback(mHandler, () -> onCreateAnimation(targetCompats, result))); return; } if (mLauncher.hasSomeInvisibleFlag(PENDING_INVISIBLE_BY_WALLPAPER_ANIMATION)) { mLauncher.addForceInvisibleFlag(INVISIBLE_BY_PENDING_FLAGS); mLauncher.getStateManager().moveToRestState(); } AnimatorSet anim = null; RemoteAnimationProvider provider = mRemoteAnimationProvider; if (provider != null) { anim = provider.createWindowAnimation(targetCompats); } if (anim == null) { anim = new AnimatorSet(); anim.play(fromUnlock ? getUnlockWindowAnimator(targetCompats) : getClosingWindowAnimators(targetCompats)); // 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 // contents of launcher unless we know that we are animating home as a result // of the home button press with quickstep, which will result in launcher being // started on touch down, prior to the animation home (and won't be in the // 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(targetCompats, MODE_OPENING) || mLauncher.isForceInvisible()) { // Only register the content animation for cancellation when state changes mLauncher.getStateManager().setCurrentAnimation(anim); if (fromUnlock) { Pair<AnimatorSet, Runnable> contentAnimator = getLauncherContentAnimator(false /* isAppOpening */, new float[] {mContentTransY, 0}); contentAnimator.first.setStartDelay(0); anim.play(contentAnimator.first); anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { contentAnimator.second.run(); } }); } else { createLauncherResumeAnimation(anim); } } } mLauncher.clearForceInvisibleFlag(INVISIBLE_ALL); result.setAnimation(anim); } }; RemoteAnimationRunnerCompat getWallpaperOpenRunner(boolean fromUnlock) { return new WallpaperOpenLauncherAnimationRunner(mHandler, false /* startAtFrontOfQueue */, fromUnlock); } /** Loading Loading @@ -773,4 +712,79 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans return mLauncher.checkSelfPermission(CONTROL_REMOTE_APP_TRANSITION_PERMISSION) == PackageManager.PERMISSION_GRANTED; } /** * Remote animation runner for animation from the app to Launcher, including recents. */ class WallpaperOpenLauncherAnimationRunner extends LauncherAnimationRunner { private final boolean mFromUnlock; public WallpaperOpenLauncherAnimationRunner(Handler handler, boolean startAtFrontOfQueue, boolean fromUnlock) { super(handler, startAtFrontOfQueue); mFromUnlock = fromUnlock; } @Override public void onCreateAnimation(RemoteAnimationTargetCompat[] targetCompats, LauncherAnimationRunner.AnimationResult result) { if (!mLauncher.hasBeenResumed()) { // If launcher is not resumed, wait until new async-frame after resume mLauncher.setOnResumeCallback(() -> postAsyncCallback(mHandler, () -> onCreateAnimation(targetCompats, result))); return; } if (mLauncher.hasSomeInvisibleFlag(PENDING_INVISIBLE_BY_WALLPAPER_ANIMATION)) { mLauncher.addForceInvisibleFlag(INVISIBLE_BY_PENDING_FLAGS); mLauncher.getStateManager().moveToRestState(); } AnimatorSet anim = null; RemoteAnimationProvider provider = mRemoteAnimationProvider; if (provider != null) { anim = provider.createWindowAnimation(targetCompats); } if (anim == null) { anim = new AnimatorSet(); anim.play(mFromUnlock ? getUnlockWindowAnimator(targetCompats) : getClosingWindowAnimators(targetCompats)); // 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 // contents of launcher unless we know that we are animating home as a result // of the home button press with quickstep, which will result in launcher being // started on touch down, prior to the animation home (and won't be in the // 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(targetCompats, MODE_OPENING) || mLauncher.isForceInvisible()) { // Only register the content animation for cancellation when state changes mLauncher.getStateManager().setCurrentAnimation(anim); if (mFromUnlock) { Pair<AnimatorSet, Runnable> contentAnimator = getLauncherContentAnimator(false /* isAppOpening */, new float[] {mContentTransY, 0}); contentAnimator.first.setStartDelay(0); anim.play(contentAnimator.first); anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { contentAnimator.second.run(); } }); } else { createLauncherResumeAnimation(anim); } } } mLauncher.clearForceInvisibleFlag(INVISIBLE_ALL); result.setAnimation(anim); } } }