Animate split divider
* TODO currently it doesn't animate when dragging a split task back down because we need to sync that with the other task scaling animation playback controllers. * It also doesn't animate in when opening a split pair from overview because I think shell is setting it to be visible before the divider leash even makes it to launcher Bug: 202914644 Change-Id: I6c60cffdb63aa262d0b547f85acc604c0c8a3637
This commit is contained in:
parent
a21e47c930
commit
0d40e19c4a
|
@ -176,6 +176,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
|||
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;
|
||||
|
|
|
@ -818,7 +818,8 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
|||
mRecentsAnimationStartCallbacks.clear();
|
||||
}
|
||||
|
||||
TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps, false);
|
||||
TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps,
|
||||
false /*shown*/, true /*animate*/);
|
||||
|
||||
// Only add the callback to enable the input consumer after we actually have the controller
|
||||
mStateCallback.runOnceAtState(STATE_APP_CONTROLLER_RECEIVED | STATE_GESTURE_STARTED,
|
||||
|
@ -835,7 +836,8 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
|||
mStateCallback.setStateOnUiThread(STATE_GESTURE_CANCELLED | STATE_HANDLER_INVALIDATED);
|
||||
|
||||
if (mRecentsAnimationTargets != null) {
|
||||
TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps, true);
|
||||
TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps,
|
||||
true /*shown*/, true /*animate*/);
|
||||
}
|
||||
|
||||
// Defer clearing the controller and the targets until after we've updated the state
|
||||
|
@ -985,8 +987,8 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
|||
mStateCallback.setState(STATE_RESUME_LAST_TASK);
|
||||
}
|
||||
if (mRecentsAnimationTargets != null) {
|
||||
TaskViewUtils.setSplitAuxiliarySurfacesShown(
|
||||
mRecentsAnimationTargets.nonApps, true);
|
||||
TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps,
|
||||
true /*shown*/, true /*animate*/);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1637,7 +1639,8 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
|||
mActivityInterface.onTransitionCancelled(wasVisible, mGestureState.getEndTarget());
|
||||
|
||||
if (mRecentsAnimationTargets != null) {
|
||||
TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps, true);
|
||||
TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps,
|
||||
true /*shown*/, true /*animate*/);
|
||||
}
|
||||
|
||||
// Leave the pending invisible flag, as it may be used by wallpaper open animation.
|
||||
|
@ -1878,7 +1881,8 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
|||
@Override
|
||||
public void onRecentsAnimationFinished(RecentsAnimationController controller) {
|
||||
if (!controller.getFinishTargetIsLauncher()) {
|
||||
TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps, true);
|
||||
TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps,
|
||||
true /*shown*/, true /*animate*/);
|
||||
}
|
||||
mRecentsAnimationController = null;
|
||||
mRecentsAnimationTargets = null;
|
||||
|
|
|
@ -20,6 +20,7 @@ import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
|||
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
|
||||
import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_INITIALIZED;
|
||||
import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_STARTED;
|
||||
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
|
@ -27,6 +28,7 @@ import android.content.Intent;
|
|||
import android.os.Bundle;
|
||||
import android.os.SystemProperties;
|
||||
import android.util.Log;
|
||||
import android.view.RemoteAnimationTarget;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.UiThread;
|
||||
|
@ -42,6 +44,7 @@ import com.android.systemui.shared.system.RemoteTransitionCompat;
|
|||
import com.android.systemui.shared.system.TaskStackChangeListener;
|
||||
import com.android.systemui.shared.system.TaskStackChangeListeners;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAnimationListener {
|
||||
|
@ -150,6 +153,17 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
|
|||
public void onTasksAppeared(RemoteAnimationTargetCompat[] appearedTaskTargets) {
|
||||
RemoteAnimationTargetCompat appearedTaskTarget = appearedTaskTargets[0];
|
||||
BaseActivityInterface activityInterface = mLastGestureState.getActivityInterface();
|
||||
// Convert appTargets to type RemoteAnimationTarget for all apps except Home app
|
||||
RemoteAnimationTarget[] nonHomeApps = Arrays.stream(appearedTaskTargets)
|
||||
.filter(remoteAnimationTarget ->
|
||||
remoteAnimationTarget.activityType != ACTIVITY_TYPE_HOME)
|
||||
.map(RemoteAnimationTargetCompat::unwrap)
|
||||
.toArray(RemoteAnimationTarget[]::new);
|
||||
|
||||
RemoteAnimationTarget[] nonAppTargets =
|
||||
SystemUiProxy.INSTANCE.getNoCreate()
|
||||
.onGoingToRecentsLegacy(false, nonHomeApps);
|
||||
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get() && activityInterface.isInLiveTileMode()
|
||||
&& activityInterface.getCreatedActivity() != null) {
|
||||
RecentsView recentsView =
|
||||
|
@ -158,7 +172,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
|
|||
recentsView.launchSideTaskInLiveTileMode(appearedTaskTarget.taskId,
|
||||
appearedTaskTargets,
|
||||
new RemoteAnimationTargetCompat[0] /* wallpaper */,
|
||||
new RemoteAnimationTargetCompat[0] /* nonApps */);
|
||||
RemoteAnimationTargetCompat.wrap(nonAppTargets) /* nonApps */);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import static com.android.launcher3.QuickstepTransitionManager.ANIMATION_NAV_FAD
|
|||
import static com.android.launcher3.QuickstepTransitionManager.NAV_FADE_IN_INTERPOLATOR;
|
||||
import static com.android.launcher3.QuickstepTransitionManager.NAV_FADE_OUT_INTERPOLATOR;
|
||||
import static com.android.launcher3.QuickstepTransitionManager.RECENTS_LAUNCH_DURATION;
|
||||
import static com.android.launcher3.QuickstepTransitionManager.SPLIT_DIVIDER_ANIM_DURATION;
|
||||
import static com.android.launcher3.QuickstepTransitionManager.SPLIT_LAUNCH_DURATION;
|
||||
import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
|
@ -536,7 +537,8 @@ public final class TaskViewUtils {
|
|||
nonAppTargets, depthController, pa);
|
||||
if (launcherClosing) {
|
||||
// TODO(b/182592057): differentiate between "restore split" vs "launch fullscreen app"
|
||||
TaskViewUtils.setSplitAuxiliarySurfacesShown(nonAppTargets, true);
|
||||
TaskViewUtils.setSplitAuxiliarySurfacesShown(nonAppTargets,
|
||||
true /*shown*/, true /*animate*/, pa);
|
||||
}
|
||||
|
||||
Animator childStateAnimation = null;
|
||||
|
@ -592,19 +594,88 @@ public final class TaskViewUtils {
|
|||
}
|
||||
|
||||
public static void setSplitAuxiliarySurfacesShown(RemoteAnimationTargetCompat[] nonApps,
|
||||
boolean shown) {
|
||||
// TODO(b/182592057): make this part of the animations instead.
|
||||
if (nonApps != null && nonApps.length > 0) {
|
||||
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
|
||||
for (int i = 0; i < nonApps.length; ++i) {
|
||||
final RemoteAnimationTargetCompat targ = nonApps[i];
|
||||
final SurfaceControl leash = targ.leash.getSurfaceControl();
|
||||
if (targ.windowType == TYPE_DOCK_DIVIDER && leash != null) {
|
||||
t.setVisibility(leash, shown);
|
||||
boolean shown, boolean animate) {
|
||||
setSplitAuxiliarySurfacesShown(nonApps, shown, animate,null);
|
||||
}
|
||||
|
||||
private static void setSplitAuxiliarySurfacesShown(
|
||||
@NonNull RemoteAnimationTargetCompat[] nonApps, boolean shown, boolean animate,
|
||||
@Nullable PendingAnimation splitLaunchAnimation) {
|
||||
if (nonApps == null || nonApps.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
|
||||
SurfaceControl[] auxiliarySurfaces = new SurfaceControl[nonApps.length];
|
||||
boolean hasSurfaceToAnimate = false;
|
||||
for (int i = 0; i < nonApps.length; ++i) {
|
||||
final RemoteAnimationTargetCompat targ = nonApps[i];
|
||||
final SurfaceControl leash = targ.leash.getSurfaceControl();
|
||||
if (targ.windowType == TYPE_DOCK_DIVIDER && leash != null) {
|
||||
auxiliarySurfaces[i] = leash;
|
||||
hasSurfaceToAnimate = true;
|
||||
}
|
||||
}
|
||||
if (!hasSurfaceToAnimate) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!animate) {
|
||||
for (SurfaceControl leash : auxiliarySurfaces) {
|
||||
t.setAlpha(leash, shown ? 1 : 0);
|
||||
if (shown) {
|
||||
t.show(leash);
|
||||
} else {
|
||||
t.hide(leash);
|
||||
}
|
||||
}
|
||||
t.apply();
|
||||
t.close();
|
||||
return;
|
||||
}
|
||||
|
||||
ValueAnimator dockFadeAnimator = ValueAnimator.ofFloat(0f, 1f);
|
||||
dockFadeAnimator.addUpdateListener(valueAnimator -> {
|
||||
float progress = valueAnimator.getAnimatedFraction();
|
||||
for (SurfaceControl leash : auxiliarySurfaces) {
|
||||
t.setAlpha(leash, shown ? progress : 1 - progress);
|
||||
}
|
||||
t.apply();
|
||||
});
|
||||
dockFadeAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
super.onAnimationStart(animation);
|
||||
if (shown) {
|
||||
for (SurfaceControl leash : auxiliarySurfaces) {
|
||||
t.setAlpha(leash, 0);
|
||||
t.show(leash);
|
||||
}
|
||||
t.apply();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
super.onAnimationEnd(animation);
|
||||
if (!shown) {
|
||||
for (SurfaceControl leash : auxiliarySurfaces) {
|
||||
t.hide(leash);
|
||||
}
|
||||
t.apply();
|
||||
}
|
||||
t.close();
|
||||
}
|
||||
});
|
||||
dockFadeAnimator.setDuration(SPLIT_DIVIDER_ANIM_DURATION);
|
||||
if (splitLaunchAnimation != null) {
|
||||
// If split apps are launching, we want to delay showing the divider bar until the very
|
||||
// end once the apps are mostly in place. This is because we aren't moving the divider
|
||||
// leash in the relative position with the launching apps.
|
||||
dockFadeAnimator.setStartDelay(
|
||||
splitLaunchAnimation.getDuration() - SPLIT_DIVIDER_ANIM_DURATION);
|
||||
splitLaunchAnimation.add(dockFadeAnimator);
|
||||
} else {
|
||||
dockFadeAnimator.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4172,8 +4172,10 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
|||
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);
|
||||
.getTransformParams().getTargetSet().nonApps,
|
||||
true /*shown*/, false /*animate*/);
|
||||
}
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get() && tv.isRunningTask()) {
|
||||
finishRecentsAnimation(false /* toRecents */, null);
|
||||
|
|
|
@ -628,11 +628,8 @@ public class TaskView extends FrameLayout implements Reusable {
|
|||
Arrays.stream(topLeftParams.getTargetSet().wallpapers),
|
||||
Arrays.stream(rightBottomParams.getTargetSet().wallpapers))
|
||||
.toArray(RemoteAnimationTargetCompat[]::new);
|
||||
RemoteAnimationTargetCompat[] nonApps = Stream.concat(
|
||||
Arrays.stream(topLeftParams.getTargetSet().nonApps),
|
||||
Arrays.stream(rightBottomParams.getTargetSet().nonApps))
|
||||
.toArray(RemoteAnimationTargetCompat[]::new);
|
||||
targets = new RemoteAnimationTargets(apps, wallpapers, nonApps,
|
||||
targets = new RemoteAnimationTargets(apps, wallpapers,
|
||||
topLeftParams.getTargetSet().nonApps,
|
||||
topLeftParams.getTargetSet().targetMode);
|
||||
}
|
||||
if (targets == null) {
|
||||
|
|
Loading…
Reference in New Issue