Improve maximizing dock/clip reveal animation
am: f97ed9271f
* commit 'f97ed9271fef192f5411206e781eb3519c144ace':
Improve maximizing dock/clip reveal animation
This commit is contained in:
@@ -216,6 +216,9 @@ public class AppTransition implements Dump {
|
||||
private final ArrayList<AppTransitionListener> mListeners = new ArrayList<>();
|
||||
private final ExecutorService mDefaultExecutor = Executors.newSingleThreadExecutor();
|
||||
|
||||
private int mLastClipRevealMaxTranslation;
|
||||
private boolean mLastHadClipReveal;
|
||||
|
||||
AppTransition(Context context, WindowManagerService service) {
|
||||
mContext = context;
|
||||
mService = service;
|
||||
@@ -337,6 +340,9 @@ public class AppTransition implements Dump {
|
||||
if (!isRunning()) {
|
||||
mAppTransitionState = APP_STATE_IDLE;
|
||||
notifyAppTransitionPendingLocked();
|
||||
mLastHadClipReveal = false;
|
||||
mLastClipRevealMaxTranslation = 0;
|
||||
mLastClipRevealTransitionDuration = DEFAULT_APP_TRANSITION_DURATION;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -641,10 +647,27 @@ public class AppTransition implements Dump {
|
||||
bitmap, new Rect(left, top, left + width, top + height));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the duration of the last clip reveal animation
|
||||
*/
|
||||
long getLastClipRevealTransitionDuration() {
|
||||
return mLastClipRevealTransitionDuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the maximum distance the app surface is traveling of the last clip reveal animation
|
||||
*/
|
||||
int getLastClipRevealMaxTranslation() {
|
||||
return mLastClipRevealMaxTranslation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if in the last app transition had a clip reveal animation, false otherwise
|
||||
*/
|
||||
boolean hadClipRevealAnimation() {
|
||||
return mLastHadClipReveal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the duration for the clip reveal animation. If the clip is "cut off", meaning that
|
||||
* the start rect is outside of the target rect, and there is a lot of movement going on.
|
||||
@@ -748,7 +771,13 @@ public class AppTransition implements Dump {
|
||||
set.setZAdjustment(Animation.ZORDER_TOP);
|
||||
set.initialize(appWidth, appHeight, appWidth, appHeight);
|
||||
anim = set;
|
||||
mLastHadClipReveal = true;
|
||||
mLastClipRevealTransitionDuration = duration;
|
||||
|
||||
// If the start rect was full inside the target rect (cutOff == false), we don't need
|
||||
// to store the translation, because it's only used if cutOff == true.
|
||||
mLastClipRevealMaxTranslation = cutOff
|
||||
? Math.max(Math.abs(translationY), Math.abs(translationX)) : 0;
|
||||
} else {
|
||||
final long duration;
|
||||
switch (transit) {
|
||||
|
||||
@@ -21,14 +21,12 @@ import android.graphics.Rect;
|
||||
import android.os.RemoteCallbackList;
|
||||
import android.os.RemoteException;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
import android.view.DisplayInfo;
|
||||
import android.view.IDockedStackListener;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.PathInterpolator;
|
||||
|
||||
import com.android.server.wm.DimLayer.DimLayerUser;
|
||||
|
||||
@@ -52,6 +50,30 @@ public class DockedStackDividerController implements DimLayerUser {
|
||||
|
||||
private static final String TAG = TAG_WITH_CLASS_NAME ? "DockedStackDividerController" : TAG_WM;
|
||||
|
||||
/**
|
||||
* The fraction during the maximize/clip reveal animation the divider meets the edge of the clip
|
||||
* revealing surface at the earliest.
|
||||
*/
|
||||
private static final float CLIP_REVEAL_MEET_EARLIEST = 0.6f;
|
||||
|
||||
/**
|
||||
* The fraction during the maximize/clip reveal animation the divider meets the edge of the clip
|
||||
* revealing surface at the latest.
|
||||
*/
|
||||
private static final float CLIP_REVEAL_MEET_LAST = 1f;
|
||||
|
||||
/**
|
||||
* If the app translates at least CLIP_REVEAL_MEET_FRACTION_MIN * minimize distance, we start
|
||||
* meet somewhere between {@link #CLIP_REVEAL_MEET_LAST} and {@link #CLIP_REVEAL_MEET_EARLIEST}.
|
||||
*/
|
||||
private static final float CLIP_REVEAL_MEET_FRACTION_MIN = 0.4f;
|
||||
|
||||
/**
|
||||
* If the app translates equals or more than CLIP_REVEAL_MEET_FRACTION_MIN * minimize distance,
|
||||
* we meet at {@link #CLIP_REVEAL_MEET_EARLIEST}.
|
||||
*/
|
||||
private static final float CLIP_REVEAL_MEET_FRACTION_MAX = 0.8f;
|
||||
|
||||
private final WindowManagerService mService;
|
||||
private final DisplayContent mDisplayContent;
|
||||
private final int mDividerWindowWidth;
|
||||
@@ -74,6 +96,7 @@ public class DockedStackDividerController implements DimLayerUser {
|
||||
private float mAnimationTarget;
|
||||
private long mAnimationDuration;
|
||||
private final Interpolator mMinimizedDockInterpolator;
|
||||
private float mMaximizeMeetFraction;
|
||||
|
||||
DockedStackDividerController(WindowManagerService service, DisplayContent displayContent) {
|
||||
mService = service;
|
||||
@@ -342,6 +365,7 @@ public class DockedStackDividerController implements DimLayerUser {
|
||||
return false;
|
||||
}
|
||||
|
||||
final TaskStack stack = mDisplayContent.getDockedStackVisibleForUserLocked();
|
||||
if (!mAnimationStarted) {
|
||||
mAnimationStarted = true;
|
||||
mAnimationStartTime = now;
|
||||
@@ -350,16 +374,15 @@ public class DockedStackDividerController implements DimLayerUser {
|
||||
: DEFAULT_APP_TRANSITION_DURATION;
|
||||
mAnimationDuration = (long)
|
||||
(transitionDuration * mService.getTransitionAnimationScaleLocked());
|
||||
mMaximizeMeetFraction = getClipRevealMeetFraction(stack);
|
||||
notifyDockedStackMinimizedChanged(mMinimizedDock,
|
||||
mAnimationDuration);
|
||||
(long) (mAnimationDuration * mMaximizeMeetFraction));
|
||||
}
|
||||
float t = Math.min(1f, (float) (now - mAnimationStartTime) / mAnimationDuration);
|
||||
t = (isAnimationMaximizing() ? TOUCH_RESPONSE_INTERPOLATOR : mMinimizedDockInterpolator)
|
||||
.getInterpolation(t);
|
||||
final TaskStack stack = mDisplayContent.getDockedStackVisibleForUserLocked();
|
||||
if (stack != null) {
|
||||
final float amount = t * mAnimationTarget + (1 - t) * mAnimationStart;
|
||||
if (stack.setAdjustedForMinimizedDock(amount)) {
|
||||
if (stack.setAdjustedForMinimizedDock(getMinimizeAmount(stack, t))) {
|
||||
mService.mWindowPlacerLocked.performSurfacePlacement();
|
||||
}
|
||||
}
|
||||
@@ -371,6 +394,54 @@ public class DockedStackDividerController implements DimLayerUser {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount how much to minimize a stack depending on the interpolated fraction t.
|
||||
*/
|
||||
private float getMinimizeAmount(TaskStack stack, float t) {
|
||||
final float naturalAmount = t * mAnimationTarget + (1 - t) * mAnimationStart;
|
||||
if (isAnimationMaximizing()) {
|
||||
return adjustMaximizeAmount(stack, t, naturalAmount);
|
||||
} else {
|
||||
return naturalAmount;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When maximizing the stack during a clip reveal transition, this adjusts the minimize amount
|
||||
* during the transition such that the edge of the clip reveal rect is met earlier in the
|
||||
* transition so we don't create a visible "hole", but only if both the clip reveal and the
|
||||
* docked stack divider start from about the same portion on the screen.
|
||||
*/
|
||||
private float adjustMaximizeAmount(TaskStack stack, float t, float naturalAmount) {
|
||||
if (mMaximizeMeetFraction == 1f) {
|
||||
return naturalAmount;
|
||||
}
|
||||
final int minimizeDistance = stack.getMinimizeDistance();
|
||||
float startPrime = mService.mAppTransition.getLastClipRevealMaxTranslation()
|
||||
/ (float) minimizeDistance;
|
||||
final float amountPrime = t * mAnimationTarget + (1 - t) * startPrime;
|
||||
final float t2 = Math.min(t / mMaximizeMeetFraction, 1);
|
||||
return amountPrime * t2 + naturalAmount * (1 - t2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the animation fraction at which the docked stack has to meet the clip reveal
|
||||
* edge. See {@link #adjustMaximizeAmount}.
|
||||
*/
|
||||
private float getClipRevealMeetFraction(TaskStack stack) {
|
||||
if (!isAnimationMaximizing() || stack == null ||
|
||||
!mService.mAppTransition.hadClipRevealAnimation()) {
|
||||
return 1f;
|
||||
}
|
||||
final int minimizeDistance = stack.getMinimizeDistance();
|
||||
final float fraction = Math.abs(mService.mAppTransition.getLastClipRevealMaxTranslation())
|
||||
/ (float) minimizeDistance;
|
||||
final float t = Math.max(0, Math.min(1, (fraction - CLIP_REVEAL_MEET_FRACTION_MIN)
|
||||
/ (CLIP_REVEAL_MEET_FRACTION_MAX - CLIP_REVEAL_MEET_FRACTION_MIN)));
|
||||
return CLIP_REVEAL_MEET_EARLIEST
|
||||
+ (1 - t) * (CLIP_REVEAL_MEET_LAST - CLIP_REVEAL_MEET_EARLIEST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFullscreen() {
|
||||
return false;
|
||||
|
||||
@@ -876,6 +876,26 @@ public class TaskStack implements DimLayer.DimLayerUser,
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the distance in pixels how much the stack gets minimized from it's original size
|
||||
*/
|
||||
int getMinimizeDistance() {
|
||||
final int dockSide = getDockSide();
|
||||
if (dockSide == DOCKED_INVALID) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dockSide == DOCKED_TOP) {
|
||||
mService.getStableInsetsLocked(mTmpRect);
|
||||
int topInset = mTmpRect.top;
|
||||
return mBounds.bottom - topInset;
|
||||
} else if (dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT) {
|
||||
return mBounds.width() - mDockedStackMinimizeThickness;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the adjustment depending on it's current state.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user