Merge "Update status bar transition start time" into sc-qpr1-dev am: 5784ba0c38 am: 65e4e7d7fa

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15879493

Change-Id: I3acd865621921efcb708bcdfcb447c1bc77af0b4
This commit is contained in:
Pablo Gamito
2021-09-23 05:34:54 +00:00
committed by Automerger Merge Worker
2 changed files with 104 additions and 13 deletions

View File

@@ -57,6 +57,9 @@ public class TranslateAnimation extends Animation {
/** @hide */ /** @hide */
protected float mToYDelta; protected float mToYDelta;
private int mWidth;
private int mParentWidth;
/** /**
* Constructor used when a TranslateAnimation is loaded from a resource. * Constructor used when a TranslateAnimation is loaded from a resource.
* *
@@ -179,5 +182,60 @@ public class TranslateAnimation extends Animation {
mToXDelta = resolveSize(mToXType, mToXValue, width, parentWidth); mToXDelta = resolveSize(mToXType, mToXValue, width, parentWidth);
mFromYDelta = resolveSize(mFromYType, mFromYValue, height, parentHeight); mFromYDelta = resolveSize(mFromYType, mFromYValue, height, parentHeight);
mToYDelta = resolveSize(mToYType, mToYValue, height, parentHeight); mToYDelta = resolveSize(mToYType, mToYValue, height, parentHeight);
mWidth = width;
mParentWidth = parentWidth;
}
/**
* Checks whether or not the translation is exclusively an x axis translation.
*
* @hide
*/
public boolean isXAxisTransition() {
return mFromXDelta - mToXDelta != 0 && mFromYDelta - mToYDelta == 0;
}
/**
* Checks whether or not the translation is a full width x axis slide in or out translation.
*
* @hide
*/
public boolean isFullWidthTranslate() {
boolean isXAxisSlideTransition =
isSlideInLeft() || isSlideOutRight() || isSlideInRight() || isSlideOutLeft();
return mWidth == mParentWidth && isXAxisSlideTransition;
}
private boolean isSlideInLeft() {
boolean startsOutOfParentOnLeft = mFromXDelta <= -mWidth;
return startsOutOfParentOnLeft && endsXEnclosedWithinParent();
}
private boolean isSlideOutRight() {
boolean endOutOfParentOnRight = mToXDelta >= mParentWidth;
return startsXEnclosedWithinParent() && endOutOfParentOnRight;
}
private boolean isSlideInRight() {
boolean startsOutOfParentOnRight = mFromXDelta >= mParentWidth;
return startsOutOfParentOnRight && endsXEnclosedWithinParent();
}
private boolean isSlideOutLeft() {
boolean endOutOfParentOnLeft = mToXDelta <= -mWidth;
return startsXEnclosedWithinParent() && endOutOfParentOnLeft;
}
private boolean endsXEnclosedWithinParent() {
return mWidth <= mParentWidth
&& mToXDelta + mWidth <= mParentWidth
&& mToXDelta >= 0;
}
private boolean startsXEnclosedWithinParent() {
return mWidth <= mParentWidth
&& mFromXDelta + mWidth <= mParentWidth
&& mFromXDelta >= 0;
} }
} }

View File

@@ -125,16 +125,30 @@ public class WindowAnimationSpec implements AnimationSpec {
@Override @Override
public long calculateStatusBarTransitionStartTime() { public long calculateStatusBarTransitionStartTime() {
TranslateAnimation openTranslateAnimation = findTranslateAnimation(mAnimation); TranslateAnimation openTranslateAnimation = findTranslateAnimation(mAnimation);
if (openTranslateAnimation != null) {
// Some interpolators are extremely quickly mostly finished, but not completely. For if (openTranslateAnimation != null) {
// our purposes, we need to find the fraction for which ther interpolator is mostly if (openTranslateAnimation.isXAxisTransition()
// there, and use that value for the calculation. && openTranslateAnimation.isFullWidthTranslate()) {
float t = findAlmostThereFraction(openTranslateAnimation.getInterpolator()); // On X axis transitions that are fullscreen (heuristic for task like transitions)
return SystemClock.uptimeMillis() // we want the status bar to animate right in the middle of the translation when
+ openTranslateAnimation.getStartOffset() // the windows/tasks have each moved half way across.
+ (long)(openTranslateAnimation.getDuration() * t) float t = findMiddleOfTranslationFraction(openTranslateAnimation.getInterpolator());
- STATUS_BAR_TRANSITION_DURATION;
return SystemClock.uptimeMillis()
+ openTranslateAnimation.getStartOffset()
+ (long) (openTranslateAnimation.getDuration() * t)
- (long) (STATUS_BAR_TRANSITION_DURATION * 0.5);
} else {
// Some interpolators are extremely quickly mostly finished, but not completely. For
// our purposes, we need to find the fraction for which their interpolator is mostly
// there, and use that value for the calculation.
float t = findAlmostThereFraction(openTranslateAnimation.getInterpolator());
return SystemClock.uptimeMillis()
+ openTranslateAnimation.getStartOffset()
+ (long) (openTranslateAnimation.getDuration() * t)
- STATUS_BAR_TRANSITION_DURATION;
}
} else { } else {
return SystemClock.uptimeMillis(); return SystemClock.uptimeMillis();
} }
@@ -183,20 +197,39 @@ public class WindowAnimationSpec implements AnimationSpec {
} }
/** /**
* Binary searches for a {@code t} such that there exists a {@code -0.01 < eps < 0.01} for which * Finds the fraction of the animation's duration at which the transition is almost done with a
* {@code interpolator(t + eps) > 0.99}. * maximal error of 0.01 when it is animated with {@code interpolator}.
*/ */
private static float findAlmostThereFraction(Interpolator interpolator) { private static float findAlmostThereFraction(Interpolator interpolator) {
return findInterpolationAdjustedTargetFraction(interpolator, 0.99f, 0.01f);
}
/**
* Finds the fraction of the animation's duration at which the transition is spacially half way
* done with a maximal error of 0.01 when it is animated with {@code interpolator}.
*/
private float findMiddleOfTranslationFraction(Interpolator interpolator) {
return findInterpolationAdjustedTargetFraction(interpolator, 0.5f, 0.01f);
}
/**
* Binary searches for a {@code val} such that there exists an {@code -0.01 < epsilon < 0.01}
* for which {@code interpolator(val + epsilon) > target}.
*/
private static float findInterpolationAdjustedTargetFraction(
Interpolator interpolator, float target, float epsilon) {
float val = 0.5f; float val = 0.5f;
float adj = 0.25f; float adj = 0.25f;
while (adj >= 0.01f) {
if (interpolator.getInterpolation(val) < 0.99f) { while (adj >= epsilon) {
if (interpolator.getInterpolation(val) < target) {
val += adj; val += adj;
} else { } else {
val -= adj; val -= adj;
} }
adj /= 2; adj /= 2;
} }
return val; return val;
} }