Merge "Ensure Recents Go layout finishes before remote anim begins" into ub-launcher3-qt-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
09edbf3c73
@@ -1,16 +1,20 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
@@ -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) {
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user