Merge "Log.wtf when float properties in ViewState are set to NaN." into tm-qpr-dev am: b65bc409a9
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20130931 Change-Id: Iea250fa9a92a6af7ef43b363cf2ab5ae7985829b Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -189,22 +189,22 @@ public class NotificationShelf extends ActivatableNotificationView implements
|
||||
viewState.copyFrom(lastViewState);
|
||||
|
||||
viewState.height = getIntrinsicHeight();
|
||||
viewState.zTranslation = ambientState.getBaseZHeight();
|
||||
viewState.setZTranslation(ambientState.getBaseZHeight());
|
||||
viewState.clipTopAmount = 0;
|
||||
|
||||
if (ambientState.isExpansionChanging() && !ambientState.isOnKeyguard()) {
|
||||
float expansion = ambientState.getExpansionFraction();
|
||||
if (ambientState.isBouncerInTransit()) {
|
||||
viewState.alpha = aboutToShowBouncerProgress(expansion);
|
||||
viewState.setAlpha(aboutToShowBouncerProgress(expansion));
|
||||
} else {
|
||||
viewState.alpha = ShadeInterpolation.getContentAlpha(expansion);
|
||||
viewState.setAlpha(ShadeInterpolation.getContentAlpha(expansion));
|
||||
}
|
||||
} else {
|
||||
viewState.alpha = 1f - ambientState.getHideAmount();
|
||||
viewState.setAlpha(1f - ambientState.getHideAmount());
|
||||
}
|
||||
viewState.belowSpeedBump = mHostLayoutController.getSpeedBumpIndex() == 0;
|
||||
viewState.hideSensitive = false;
|
||||
viewState.xTranslation = getTranslationX();
|
||||
viewState.setXTranslation(getTranslationX());
|
||||
viewState.hasItemsInStableShelf = lastViewState.inShelf;
|
||||
viewState.firstViewInShelf = algorithmState.firstViewInShelf;
|
||||
if (mNotGoneIndex != -1) {
|
||||
@@ -230,7 +230,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
|
||||
}
|
||||
|
||||
final float stackEnd = ambientState.getStackY() + ambientState.getStackHeight();
|
||||
viewState.yTranslation = stackEnd - viewState.height;
|
||||
viewState.setYTranslation(stackEnd - viewState.height);
|
||||
} else {
|
||||
viewState.hidden = true;
|
||||
viewState.location = ExpandableViewState.LOCATION_GONE;
|
||||
@@ -794,7 +794,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
|
||||
if (iconState == null) {
|
||||
return;
|
||||
}
|
||||
iconState.alpha = ICON_ALPHA_INTERPOLATOR.getInterpolation(transitionAmount);
|
||||
iconState.setAlpha(ICON_ALPHA_INTERPOLATOR.getInterpolation(transitionAmount));
|
||||
boolean isAppearing = row.isDrawingAppearAnimation() && !row.isInShelf();
|
||||
iconState.hidden = isAppearing
|
||||
|| (view instanceof ExpandableNotificationRow
|
||||
@@ -809,12 +809,12 @@ public class NotificationShelf extends ActivatableNotificationView implements
|
||||
|
||||
// Fade in icons at shelf start
|
||||
// This is important for conversation icons, which are badged and need x reset
|
||||
iconState.xTranslation = mShelfIcons.getActualPaddingStart();
|
||||
iconState.setXTranslation(mShelfIcons.getActualPaddingStart());
|
||||
|
||||
final boolean stayingInShelf = row.isInShelf() && !row.isTransformingIntoShelf();
|
||||
if (stayingInShelf) {
|
||||
iconState.iconAppearAmount = 1.0f;
|
||||
iconState.alpha = 1.0f;
|
||||
iconState.setAlpha(1.0f);
|
||||
iconState.hidden = false;
|
||||
}
|
||||
int backgroundColor = getBackgroundColorWithoutTint();
|
||||
|
||||
@@ -3376,7 +3376,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
|
||||
|
||||
private void handleFixedTranslationZ(ExpandableNotificationRow row) {
|
||||
if (row.hasExpandingChild()) {
|
||||
zTranslation = row.getTranslationZ();
|
||||
setZTranslation(row.getTranslationZ());
|
||||
clipTopAmount = row.getClipTopAmount();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -621,12 +621,12 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable {
|
||||
// initialize with the default values of the view
|
||||
mViewState.height = getIntrinsicHeight();
|
||||
mViewState.gone = getVisibility() == View.GONE;
|
||||
mViewState.alpha = 1f;
|
||||
mViewState.setAlpha(1f);
|
||||
mViewState.notGoneIndex = -1;
|
||||
mViewState.xTranslation = getTranslationX();
|
||||
mViewState.setXTranslation(getTranslationX());
|
||||
mViewState.hidden = false;
|
||||
mViewState.scaleX = getScaleX();
|
||||
mViewState.scaleY = getScaleY();
|
||||
mViewState.setScaleX(getScaleX());
|
||||
mViewState.setScaleY(getScaleY());
|
||||
mViewState.inShelf = false;
|
||||
mViewState.headsUpIsVisible = false;
|
||||
|
||||
|
||||
@@ -583,24 +583,26 @@ public class NotificationChildrenContainer extends ViewGroup
|
||||
ExpandableViewState childState = child.getViewState();
|
||||
int intrinsicHeight = child.getIntrinsicHeight();
|
||||
childState.height = intrinsicHeight;
|
||||
childState.yTranslation = yPosition + launchTransitionCompensation;
|
||||
childState.setYTranslation(yPosition + launchTransitionCompensation);
|
||||
childState.hidden = false;
|
||||
// When the group is expanded, the children cast the shadows rather than the parent
|
||||
// so use the parent's elevation here.
|
||||
childState.zTranslation =
|
||||
(childrenExpandedAndNotAnimating && mEnableShadowOnChildNotifications)
|
||||
? parentState.zTranslation
|
||||
: 0;
|
||||
if (childrenExpandedAndNotAnimating && mEnableShadowOnChildNotifications) {
|
||||
childState.setZTranslation(parentState.getZTranslation());
|
||||
} else {
|
||||
childState.setZTranslation(0);
|
||||
}
|
||||
childState.dimmed = parentState.dimmed;
|
||||
childState.hideSensitive = parentState.hideSensitive;
|
||||
childState.belowSpeedBump = parentState.belowSpeedBump;
|
||||
childState.clipTopAmount = 0;
|
||||
childState.alpha = 0;
|
||||
childState.setAlpha(0);
|
||||
if (i < firstOverflowIndex) {
|
||||
childState.alpha = showingAsLowPriority() ? expandFactor : 1.0f;
|
||||
childState.setAlpha(showingAsLowPriority() ? expandFactor : 1.0f);
|
||||
} else if (expandFactor == 1.0f && i <= lastVisibleIndex) {
|
||||
childState.alpha = (mActualHeight - childState.yTranslation) / childState.height;
|
||||
childState.alpha = Math.max(0.0f, Math.min(1.0f, childState.alpha));
|
||||
childState.setAlpha(
|
||||
(mActualHeight - childState.getYTranslation()) / childState.height);
|
||||
childState.setAlpha(Math.max(0.0f, Math.min(1.0f, childState.getAlpha())));
|
||||
}
|
||||
childState.location = parentState.location;
|
||||
childState.inShelf = parentState.inShelf;
|
||||
@@ -621,13 +623,16 @@ public class NotificationChildrenContainer extends ViewGroup
|
||||
if (mirrorView.getVisibility() == GONE) {
|
||||
mirrorView = alignView;
|
||||
}
|
||||
mGroupOverFlowState.alpha = mirrorView.getAlpha();
|
||||
mGroupOverFlowState.yTranslation += NotificationUtils.getRelativeYOffset(
|
||||
mGroupOverFlowState.setAlpha(mirrorView.getAlpha());
|
||||
float yTranslation = mGroupOverFlowState.getYTranslation()
|
||||
+ NotificationUtils.getRelativeYOffset(
|
||||
mirrorView, overflowView);
|
||||
mGroupOverFlowState.setYTranslation(yTranslation);
|
||||
}
|
||||
} else {
|
||||
mGroupOverFlowState.yTranslation += mNotificationHeaderMargin;
|
||||
mGroupOverFlowState.alpha = 0.0f;
|
||||
mGroupOverFlowState.setYTranslation(
|
||||
mGroupOverFlowState.getYTranslation() + mNotificationHeaderMargin);
|
||||
mGroupOverFlowState.setAlpha(0.0f);
|
||||
}
|
||||
}
|
||||
if (mNotificationHeader != null) {
|
||||
@@ -635,11 +640,11 @@ public class NotificationChildrenContainer extends ViewGroup
|
||||
mHeaderViewState = new ViewState();
|
||||
}
|
||||
mHeaderViewState.initFrom(mNotificationHeader);
|
||||
mHeaderViewState.zTranslation = childrenExpandedAndNotAnimating
|
||||
? parentState.zTranslation
|
||||
: 0;
|
||||
mHeaderViewState.yTranslation = mCurrentHeaderTranslation;
|
||||
mHeaderViewState.alpha = mHeaderVisibleAmount;
|
||||
mHeaderViewState.setZTranslation(childrenExpandedAndNotAnimating
|
||||
? parentState.getZTranslation()
|
||||
: 0);
|
||||
mHeaderViewState.setYTranslation(mCurrentHeaderTranslation);
|
||||
mHeaderViewState.setAlpha(mHeaderVisibleAmount);
|
||||
// The hiding is done automatically by the alpha, otherwise we'll pick it up again
|
||||
// in the next frame with the initFrom call above and have an invisible header
|
||||
mHeaderViewState.hidden = false;
|
||||
@@ -711,14 +716,14 @@ public class NotificationChildrenContainer extends ViewGroup
|
||||
// layout the divider
|
||||
View divider = mDividers.get(i);
|
||||
tmpState.initFrom(divider);
|
||||
tmpState.yTranslation = viewState.yTranslation - mDividerHeight;
|
||||
float alpha = mChildrenExpanded && viewState.alpha != 0 ? mDividerAlpha : 0;
|
||||
if (mUserLocked && !showingAsLowPriority() && viewState.alpha != 0) {
|
||||
tmpState.setYTranslation(viewState.getYTranslation() - mDividerHeight);
|
||||
float alpha = mChildrenExpanded && viewState.getAlpha() != 0 ? mDividerAlpha : 0;
|
||||
if (mUserLocked && !showingAsLowPriority() && viewState.getAlpha() != 0) {
|
||||
alpha = NotificationUtils.interpolate(0, mDividerAlpha,
|
||||
Math.min(viewState.alpha, expandFraction));
|
||||
Math.min(viewState.getAlpha(), expandFraction));
|
||||
}
|
||||
tmpState.hidden = !dividersVisible;
|
||||
tmpState.alpha = alpha;
|
||||
tmpState.setAlpha(alpha);
|
||||
tmpState.applyToView(divider);
|
||||
// There is no fake shadow to be drawn on the children
|
||||
child.setFakeShadowIntensity(0.0f, 0.0f, 0, 0);
|
||||
@@ -790,24 +795,24 @@ public class NotificationChildrenContainer extends ViewGroup
|
||||
// layout the divider
|
||||
View divider = mDividers.get(i);
|
||||
tmpState.initFrom(divider);
|
||||
tmpState.yTranslation = viewState.yTranslation - mDividerHeight;
|
||||
float alpha = mChildrenExpanded && viewState.alpha != 0 ? mDividerAlpha : 0;
|
||||
if (mUserLocked && !showingAsLowPriority() && viewState.alpha != 0) {
|
||||
tmpState.setYTranslation(viewState.getYTranslation() - mDividerHeight);
|
||||
float alpha = mChildrenExpanded && viewState.getAlpha() != 0 ? mDividerAlpha : 0;
|
||||
if (mUserLocked && !showingAsLowPriority() && viewState.getAlpha() != 0) {
|
||||
alpha = NotificationUtils.interpolate(0, mDividerAlpha,
|
||||
Math.min(viewState.alpha, expandFraction));
|
||||
Math.min(viewState.getAlpha(), expandFraction));
|
||||
}
|
||||
tmpState.hidden = !dividersVisible;
|
||||
tmpState.alpha = alpha;
|
||||
tmpState.setAlpha(alpha);
|
||||
tmpState.animateTo(divider, properties);
|
||||
// There is no fake shadow to be drawn on the children
|
||||
child.setFakeShadowIntensity(0.0f, 0.0f, 0, 0);
|
||||
}
|
||||
if (mOverflowNumber != null) {
|
||||
if (mNeverAppliedGroupState) {
|
||||
float alpha = mGroupOverFlowState.alpha;
|
||||
mGroupOverFlowState.alpha = 0;
|
||||
float alpha = mGroupOverFlowState.getAlpha();
|
||||
mGroupOverFlowState.setAlpha(0);
|
||||
mGroupOverFlowState.applyToView(mOverflowNumber);
|
||||
mGroupOverFlowState.alpha = alpha;
|
||||
mGroupOverFlowState.setAlpha(alpha);
|
||||
mNeverAppliedGroupState = false;
|
||||
}
|
||||
mGroupOverFlowState.animateTo(mOverflowNumber, properties);
|
||||
@@ -949,7 +954,7 @@ public class NotificationChildrenContainer extends ViewGroup
|
||||
child.setAlpha(start);
|
||||
ViewState viewState = new ViewState();
|
||||
viewState.initFrom(child);
|
||||
viewState.alpha = target;
|
||||
viewState.setAlpha(target);
|
||||
ALPHA_FADE_IN.setDelay(i * 50);
|
||||
viewState.animateTo(child, ALPHA_FADE_IN);
|
||||
}
|
||||
|
||||
@@ -3188,7 +3188,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
||||
|
||||
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
|
||||
private boolean shouldHunAppearFromBottom(ExpandableViewState viewState) {
|
||||
return viewState.yTranslation + viewState.height
|
||||
return viewState.getYTranslation() + viewState.height
|
||||
>= mAmbientState.getMaxHeadsUpTranslation();
|
||||
}
|
||||
|
||||
|
||||
@@ -134,23 +134,23 @@ public class StackScrollAlgorithm {
|
||||
|
||||
if (isHunGoingToShade) {
|
||||
// Keep 100% opacity for heads up notification going to shade.
|
||||
viewState.alpha = 1f;
|
||||
viewState.setAlpha(1f);
|
||||
} else if (ambientState.isOnKeyguard()) {
|
||||
// Adjust alpha for wakeup to lockscreen.
|
||||
viewState.alpha = 1f - ambientState.getHideAmount();
|
||||
viewState.setAlpha(1f - ambientState.getHideAmount());
|
||||
} else if (ambientState.isExpansionChanging()) {
|
||||
// Adjust alpha for shade open & close.
|
||||
float expansion = ambientState.getExpansionFraction();
|
||||
viewState.alpha = ambientState.isBouncerInTransit()
|
||||
viewState.setAlpha(ambientState.isBouncerInTransit()
|
||||
? BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion)
|
||||
: ShadeInterpolation.getContentAlpha(expansion);
|
||||
: ShadeInterpolation.getContentAlpha(expansion));
|
||||
}
|
||||
|
||||
// For EmptyShadeView if on keyguard, we need to control the alpha to create
|
||||
// a nice transition when the user is dragging down the notification panel.
|
||||
if (view instanceof EmptyShadeView && ambientState.isOnKeyguard()) {
|
||||
final float fractionToShade = ambientState.getFractionToShade();
|
||||
viewState.alpha = ShadeInterpolation.getContentAlpha(fractionToShade);
|
||||
viewState.setAlpha(ShadeInterpolation.getContentAlpha(fractionToShade));
|
||||
}
|
||||
|
||||
NotificationShelf shelf = ambientState.getShelf();
|
||||
@@ -166,10 +166,10 @@ public class StackScrollAlgorithm {
|
||||
continue;
|
||||
}
|
||||
|
||||
final float shelfTop = shelfState.yTranslation;
|
||||
final float viewTop = viewState.yTranslation;
|
||||
final float shelfTop = shelfState.getYTranslation();
|
||||
final float viewTop = viewState.getYTranslation();
|
||||
if (viewTop >= shelfTop) {
|
||||
viewState.alpha = 0;
|
||||
viewState.setAlpha(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -277,7 +277,7 @@ public class StackScrollAlgorithm {
|
||||
if (!child.mustStayOnScreen() || state.headsUpIsVisible) {
|
||||
clipStart = Math.max(drawStart, clipStart);
|
||||
}
|
||||
float newYTranslation = state.yTranslation;
|
||||
float newYTranslation = state.getYTranslation();
|
||||
float newHeight = state.height;
|
||||
float newNotificationEnd = newYTranslation + newHeight;
|
||||
boolean isHeadsUp = (child instanceof ExpandableNotificationRow) && child.isPinned();
|
||||
@@ -322,7 +322,8 @@ public class StackScrollAlgorithm {
|
||||
childViewState.hideSensitive = hideSensitive;
|
||||
boolean isActivatedChild = activatedChild == child;
|
||||
if (dimmed && isActivatedChild) {
|
||||
childViewState.zTranslation += 2.0f * ambientState.getZDistanceBetweenElements();
|
||||
childViewState.setZTranslation(childViewState.getZTranslation()
|
||||
+ 2.0f * ambientState.getZDistanceBetweenElements());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -527,12 +528,12 @@ public class StackScrollAlgorithm {
|
||||
|
||||
// Must set viewState.yTranslation _before_ use.
|
||||
// Incoming views have yTranslation=0 by default.
|
||||
viewState.yTranslation = algorithmState.mCurrentYPosition;
|
||||
viewState.setYTranslation(algorithmState.mCurrentYPosition);
|
||||
|
||||
float viewEnd = viewState.getYTranslation() + viewState.height + ambientState.getStackY();
|
||||
maybeUpdateHeadsUpIsVisible(viewState, ambientState.isShadeExpanded(),
|
||||
view.mustStayOnScreen(), /* topVisible */ viewState.yTranslation >= 0,
|
||||
/* viewEnd */ viewState.yTranslation + viewState.height + ambientState.getStackY(),
|
||||
/* hunMax */ ambientState.getMaxHeadsUpTranslation()
|
||||
view.mustStayOnScreen(), /* topVisible */ viewState.getYTranslation() >= 0,
|
||||
viewEnd, /* hunMax */ ambientState.getMaxHeadsUpTranslation()
|
||||
);
|
||||
if (view instanceof FooterView) {
|
||||
final boolean shadeClosed = !ambientState.isShadeExpanded();
|
||||
@@ -552,7 +553,7 @@ public class StackScrollAlgorithm {
|
||||
if (view instanceof EmptyShadeView) {
|
||||
float fullHeight = ambientState.getLayoutMaxHeight() + mMarginBottom
|
||||
- ambientState.getStackY();
|
||||
viewState.yTranslation = (fullHeight - getMaxAllowedChildHeight(view)) / 2f;
|
||||
viewState.setYTranslation((fullHeight - getMaxAllowedChildHeight(view)) / 2f);
|
||||
} else if (view != ambientState.getTrackedHeadsUpRow()) {
|
||||
if (ambientState.isExpansionChanging()) {
|
||||
// We later update shelf state, then hide views below the shelf.
|
||||
@@ -591,13 +592,13 @@ public class StackScrollAlgorithm {
|
||||
+ mPaddingBetweenElements;
|
||||
|
||||
setLocation(view.getViewState(), algorithmState.mCurrentYPosition, i);
|
||||
viewState.yTranslation += ambientState.getStackY();
|
||||
viewState.setYTranslation(viewState.getYTranslation() + ambientState.getStackY());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void updateViewWithShelf(ExpandableView view, ExpandableViewState viewState, float shelfStart) {
|
||||
viewState.yTranslation = Math.min(viewState.yTranslation, shelfStart);
|
||||
if (viewState.yTranslation >= shelfStart) {
|
||||
viewState.setYTranslation(Math.min(viewState.getYTranslation(), shelfStart));
|
||||
if (viewState.getYTranslation() >= shelfStart) {
|
||||
viewState.hidden = !view.isExpandAnimationRunning()
|
||||
&& !view.hasExpandingChild();
|
||||
viewState.inShelf = true;
|
||||
@@ -690,9 +691,9 @@ public class StackScrollAlgorithm {
|
||||
if (trackedHeadsUpRow != null) {
|
||||
ExpandableViewState childState = trackedHeadsUpRow.getViewState();
|
||||
if (childState != null) {
|
||||
float endPosition = childState.yTranslation - ambientState.getStackTranslation();
|
||||
childState.yTranslation = MathUtils.lerp(
|
||||
headsUpTranslation, endPosition, ambientState.getAppearFraction());
|
||||
float endPos = childState.getYTranslation() - ambientState.getStackTranslation();
|
||||
childState.setYTranslation(MathUtils.lerp(
|
||||
headsUpTranslation, endPos, ambientState.getAppearFraction()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -712,7 +713,7 @@ public class StackScrollAlgorithm {
|
||||
childState.location = ExpandableViewState.LOCATION_FIRST_HUN;
|
||||
}
|
||||
boolean isTopEntry = topHeadsUpEntry == row;
|
||||
float unmodifiedEndLocation = childState.yTranslation + childState.height;
|
||||
float unmodifiedEndLocation = childState.getYTranslation() + childState.height;
|
||||
if (mIsExpanded) {
|
||||
if (row.mustStayOnScreen() && !childState.headsUpIsVisible
|
||||
&& !row.showingPulsing()) {
|
||||
@@ -727,13 +728,14 @@ public class StackScrollAlgorithm {
|
||||
}
|
||||
}
|
||||
if (row.isPinned()) {
|
||||
childState.yTranslation = Math.max(childState.yTranslation, headsUpTranslation);
|
||||
childState.setYTranslation(
|
||||
Math.max(childState.getYTranslation(), headsUpTranslation));
|
||||
childState.height = Math.max(row.getIntrinsicHeight(), childState.height);
|
||||
childState.hidden = false;
|
||||
ExpandableViewState topState =
|
||||
topHeadsUpEntry == null ? null : topHeadsUpEntry.getViewState();
|
||||
if (topState != null && !isTopEntry && (!mIsExpanded
|
||||
|| unmodifiedEndLocation > topState.yTranslation + topState.height)) {
|
||||
|| unmodifiedEndLocation > topState.getYTranslation() + topState.height)) {
|
||||
// Ensure that a headsUp doesn't vertically extend further than the heads-up at
|
||||
// the top most z-position
|
||||
childState.height = row.getIntrinsicHeight();
|
||||
@@ -745,11 +747,12 @@ public class StackScrollAlgorithm {
|
||||
// heads up show full of row's content and any scroll y indicate that the
|
||||
// translationY need to move up the HUN.
|
||||
if (!mIsExpanded && isTopEntry && ambientState.getScrollY() > 0) {
|
||||
childState.yTranslation -= ambientState.getScrollY();
|
||||
childState.setYTranslation(
|
||||
childState.getYTranslation() - ambientState.getScrollY());
|
||||
}
|
||||
}
|
||||
if (row.isHeadsUpAnimatingAway()) {
|
||||
childState.yTranslation = Math.max(childState.yTranslation, mHeadsUpInset);
|
||||
childState.setYTranslation(Math.max(childState.getYTranslation(), mHeadsUpInset));
|
||||
childState.hidden = false;
|
||||
}
|
||||
}
|
||||
@@ -765,13 +768,13 @@ public class StackScrollAlgorithm {
|
||||
ExpandableViewState viewState) {
|
||||
|
||||
final float newTranslation = Math.max(quickQsOffsetHeight + stackTranslation,
|
||||
viewState.yTranslation);
|
||||
viewState.getYTranslation());
|
||||
|
||||
// Transition from collapsed pinned state to fully expanded state
|
||||
// when the pinned HUN approaches its actual location (when scrolling back to top).
|
||||
final float distToRealY = newTranslation - viewState.yTranslation;
|
||||
final float distToRealY = newTranslation - viewState.getYTranslation();
|
||||
viewState.height = (int) Math.max(viewState.height - distToRealY, collapsedHeight);
|
||||
viewState.yTranslation = newTranslation;
|
||||
viewState.setYTranslation(newTranslation);
|
||||
}
|
||||
|
||||
// Pin HUN to bottom of expanded QS
|
||||
@@ -784,10 +787,10 @@ public class StackScrollAlgorithm {
|
||||
maxHeadsUpTranslation = Math.min(maxHeadsUpTranslation, maxShelfPosition);
|
||||
|
||||
final float bottomPosition = maxHeadsUpTranslation - row.getCollapsedHeight();
|
||||
final float newTranslation = Math.min(childState.yTranslation, bottomPosition);
|
||||
final float newTranslation = Math.min(childState.getYTranslation(), bottomPosition);
|
||||
childState.height = (int) Math.min(childState.height, maxHeadsUpTranslation
|
||||
- newTranslation);
|
||||
childState.yTranslation = newTranslation;
|
||||
childState.setYTranslation(newTranslation);
|
||||
|
||||
// Animate pinned HUN bottom corners to and from original roundness.
|
||||
final float originalCornerRadius =
|
||||
@@ -859,17 +862,17 @@ public class StackScrollAlgorithm {
|
||||
float baseZ = ambientState.getBaseZHeight();
|
||||
if (child.mustStayOnScreen() && !childViewState.headsUpIsVisible
|
||||
&& !ambientState.isDozingAndNotPulsing(child)
|
||||
&& childViewState.yTranslation < ambientState.getTopPadding()
|
||||
&& childViewState.getYTranslation() < ambientState.getTopPadding()
|
||||
+ ambientState.getStackTranslation()) {
|
||||
if (childrenOnTop != 0.0f) {
|
||||
childrenOnTop++;
|
||||
} else {
|
||||
float overlap = ambientState.getTopPadding()
|
||||
+ ambientState.getStackTranslation() - childViewState.yTranslation;
|
||||
+ ambientState.getStackTranslation() - childViewState.getYTranslation();
|
||||
childrenOnTop += Math.min(1.0f, overlap / childViewState.height);
|
||||
}
|
||||
childViewState.zTranslation = baseZ
|
||||
+ childrenOnTop * zDistanceBetweenElements;
|
||||
childViewState.setZTranslation(baseZ
|
||||
+ childrenOnTop * zDistanceBetweenElements);
|
||||
} else if (shouldElevateHun) {
|
||||
// In case this is a new view that has never been measured before, we don't want to
|
||||
// elevate if we are currently expanded more then the notification
|
||||
@@ -878,28 +881,28 @@ public class StackScrollAlgorithm {
|
||||
float shelfStart = ambientState.getInnerHeight()
|
||||
- shelfHeight + ambientState.getTopPadding()
|
||||
+ ambientState.getStackTranslation();
|
||||
float notificationEnd = childViewState.yTranslation + child.getIntrinsicHeight()
|
||||
float notificationEnd = childViewState.getYTranslation() + child.getIntrinsicHeight()
|
||||
+ mPaddingBetweenElements;
|
||||
if (shelfStart > notificationEnd) {
|
||||
childViewState.zTranslation = baseZ;
|
||||
childViewState.setZTranslation(baseZ);
|
||||
} else {
|
||||
float factor = (notificationEnd - shelfStart) / shelfHeight;
|
||||
if (Float.isNaN(factor)) { // Avoid problems when the above is 0/0.
|
||||
factor = 1.0f;
|
||||
}
|
||||
factor = Math.min(factor, 1.0f);
|
||||
childViewState.zTranslation = baseZ + factor * zDistanceBetweenElements;
|
||||
childViewState.setZTranslation(baseZ + factor * zDistanceBetweenElements);
|
||||
}
|
||||
} else {
|
||||
childViewState.zTranslation = baseZ;
|
||||
childViewState.setZTranslation(baseZ);
|
||||
}
|
||||
|
||||
// We need to scrim the notification more from its surrounding content when we are pinned,
|
||||
// and we therefore elevate it higher.
|
||||
// We can use the headerVisibleAmount for this, since the value nicely goes from 0 to 1 when
|
||||
// expanding after which we have a normal elevation again.
|
||||
childViewState.zTranslation += (1.0f - child.getHeaderVisibleAmount())
|
||||
* mPinnedZTranslationExtra;
|
||||
childViewState.setZTranslation(childViewState.getZTranslation()
|
||||
+ (1.0f - child.getHeaderVisibleAmount()) * mPinnedZTranslationExtra);
|
||||
return childrenOnTop;
|
||||
}
|
||||
|
||||
|
||||
@@ -169,9 +169,9 @@ public class StackStateAnimator {
|
||||
adaptDurationWhenGoingToFullShade(child, viewState, wasAdded, animationStaggerCount);
|
||||
mAnimationProperties.delay = 0;
|
||||
if (wasAdded || mAnimationFilter.hasDelays
|
||||
&& (viewState.yTranslation != child.getTranslationY()
|
||||
|| viewState.zTranslation != child.getTranslationZ()
|
||||
|| viewState.alpha != child.getAlpha()
|
||||
&& (viewState.getYTranslation() != child.getTranslationY()
|
||||
|| viewState.getZTranslation() != child.getTranslationZ()
|
||||
|| viewState.getAlpha() != child.getAlpha()
|
||||
|| viewState.height != child.getActualHeight()
|
||||
|| viewState.clipTopAmount != child.getClipTopAmount())) {
|
||||
mAnimationProperties.delay = mCurrentAdditionalDelay
|
||||
@@ -191,7 +191,7 @@ public class StackStateAnimator {
|
||||
mAnimationProperties.duration = ANIMATION_DURATION_APPEAR_DISAPPEAR + 50
|
||||
+ (long) (100 * longerDurationFactor);
|
||||
}
|
||||
child.setTranslationY(viewState.yTranslation + startOffset);
|
||||
child.setTranslationY(viewState.getYTranslation() + startOffset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,7 +400,7 @@ public class StackStateAnimator {
|
||||
// travelled
|
||||
ExpandableViewState viewState =
|
||||
((ExpandableView) event.viewAfterChangingView).getViewState();
|
||||
translationDirection = ((viewState.yTranslation
|
||||
translationDirection = ((viewState.getYTranslation()
|
||||
- (ownPosition + actualHeight / 2.0f)) * 2 /
|
||||
actualHeight);
|
||||
translationDirection = Math.max(Math.min(translationDirection, 1.0f),-1.0f);
|
||||
@@ -433,7 +433,7 @@ public class StackStateAnimator {
|
||||
ExpandableViewState viewState = changingView.getViewState();
|
||||
mTmpState.copyFrom(viewState);
|
||||
if (event.headsUpFromBottom) {
|
||||
mTmpState.yTranslation = mHeadsUpAppearHeightBottom;
|
||||
mTmpState.setYTranslation(mHeadsUpAppearHeightBottom);
|
||||
} else {
|
||||
Runnable onAnimationEnd = null;
|
||||
if (loggable) {
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.PropertyValuesHolder;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.util.Log;
|
||||
import android.util.Property;
|
||||
import android.view.View;
|
||||
import android.view.animation.Interpolator;
|
||||
@@ -42,7 +43,7 @@ import java.lang.reflect.Modifier;
|
||||
* A state of a view. This can be used to apply a set of view properties to a view with
|
||||
* {@link com.android.systemui.statusbar.notification.stack.StackScrollState} or start
|
||||
* animations with {@link com.android.systemui.statusbar.notification.stack.StackStateAnimator}.
|
||||
*/
|
||||
*/
|
||||
public class ViewState implements Dumpable {
|
||||
|
||||
/**
|
||||
@@ -51,6 +52,7 @@ public class ViewState implements Dumpable {
|
||||
*/
|
||||
protected static final AnimationProperties NO_NEW_ANIMATIONS = new AnimationProperties() {
|
||||
AnimationFilter mAnimationFilter = new AnimationFilter();
|
||||
|
||||
@Override
|
||||
public AnimationFilter getAnimationFilter() {
|
||||
return mAnimationFilter;
|
||||
@@ -68,6 +70,7 @@ public class ViewState implements Dumpable {
|
||||
private static final int TAG_START_TRANSLATION_Y = R.id.translation_y_animator_start_value_tag;
|
||||
private static final int TAG_START_TRANSLATION_Z = R.id.translation_z_animator_start_value_tag;
|
||||
private static final int TAG_START_ALPHA = R.id.alpha_animator_start_value_tag;
|
||||
private static final String LOG_TAG = "StackViewState";
|
||||
|
||||
private static final AnimatableProperty SCALE_X_PROPERTY
|
||||
= new AnimatableProperty() {
|
||||
@@ -117,35 +120,127 @@ public class ViewState implements Dumpable {
|
||||
}
|
||||
};
|
||||
|
||||
public float alpha;
|
||||
public float xTranslation;
|
||||
public float yTranslation;
|
||||
public float zTranslation;
|
||||
public boolean gone;
|
||||
public boolean hidden;
|
||||
public float scaleX = 1.0f;
|
||||
public float scaleY = 1.0f;
|
||||
|
||||
private float mAlpha;
|
||||
private float mXTranslation;
|
||||
private float mYTranslation;
|
||||
private float mZTranslation;
|
||||
private float mScaleX = 1.0f;
|
||||
private float mScaleY = 1.0f;
|
||||
|
||||
public float getAlpha() {
|
||||
return mAlpha;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param alpha View transparency.
|
||||
*/
|
||||
public void setAlpha(float alpha) {
|
||||
if (isValidFloat(alpha, "alpha")) {
|
||||
this.mAlpha = alpha;
|
||||
}
|
||||
}
|
||||
|
||||
public float getXTranslation() {
|
||||
return mXTranslation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param xTranslation x-axis translation value for the animation.
|
||||
*/
|
||||
public void setXTranslation(float xTranslation) {
|
||||
if (isValidFloat(xTranslation, "xTranslation")) {
|
||||
this.mXTranslation = xTranslation;
|
||||
}
|
||||
}
|
||||
|
||||
public float getYTranslation() {
|
||||
return mYTranslation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param yTranslation y-axis translation value for the animation.
|
||||
*/
|
||||
public void setYTranslation(float yTranslation) {
|
||||
if (isValidFloat(yTranslation, "yTranslation")) {
|
||||
this.mYTranslation = yTranslation;
|
||||
}
|
||||
}
|
||||
|
||||
public float getZTranslation() {
|
||||
return mZTranslation;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param zTranslation z-axis translation value for the animation.
|
||||
*/
|
||||
public void setZTranslation(float zTranslation) {
|
||||
if (isValidFloat(zTranslation, "zTranslation")) {
|
||||
this.mZTranslation = zTranslation;
|
||||
}
|
||||
}
|
||||
|
||||
public float getScaleX() {
|
||||
return mScaleX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param scaleX x-axis scale property for the animation.
|
||||
*/
|
||||
public void setScaleX(float scaleX) {
|
||||
if (isValidFloat(scaleX, "scaleX")) {
|
||||
this.mScaleX = scaleX;
|
||||
}
|
||||
}
|
||||
|
||||
public float getScaleY() {
|
||||
return mScaleY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param scaleY y-axis scale property for the animation.
|
||||
*/
|
||||
public void setScaleY(float scaleY) {
|
||||
if (isValidFloat(scaleY, "scaleY")) {
|
||||
this.mScaleY = scaleY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if {@code value} is a valid float value. If it is not, logs it (using {@code name})
|
||||
* and returns false.
|
||||
*/
|
||||
private boolean isValidFloat(float value, String name) {
|
||||
if (Float.isNaN(value)) {
|
||||
Log.wtf(LOG_TAG, "Cannot set property " + name + " to NaN");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void copyFrom(ViewState viewState) {
|
||||
alpha = viewState.alpha;
|
||||
xTranslation = viewState.xTranslation;
|
||||
yTranslation = viewState.yTranslation;
|
||||
zTranslation = viewState.zTranslation;
|
||||
mAlpha = viewState.mAlpha;
|
||||
mXTranslation = viewState.mXTranslation;
|
||||
mYTranslation = viewState.mYTranslation;
|
||||
mZTranslation = viewState.mZTranslation;
|
||||
gone = viewState.gone;
|
||||
hidden = viewState.hidden;
|
||||
scaleX = viewState.scaleX;
|
||||
scaleY = viewState.scaleY;
|
||||
mScaleX = viewState.mScaleX;
|
||||
mScaleY = viewState.mScaleY;
|
||||
}
|
||||
|
||||
public void initFrom(View view) {
|
||||
alpha = view.getAlpha();
|
||||
xTranslation = view.getTranslationX();
|
||||
yTranslation = view.getTranslationY();
|
||||
zTranslation = view.getTranslationZ();
|
||||
mAlpha = view.getAlpha();
|
||||
mXTranslation = view.getTranslationX();
|
||||
mYTranslation = view.getTranslationY();
|
||||
mZTranslation = view.getTranslationZ();
|
||||
gone = view.getVisibility() == View.GONE;
|
||||
hidden = view.getVisibility() == View.INVISIBLE;
|
||||
scaleX = view.getScaleX();
|
||||
scaleY = view.getScaleY();
|
||||
mScaleX = view.getScaleX();
|
||||
mScaleY = view.getScaleY();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -161,51 +256,51 @@ public class ViewState implements Dumpable {
|
||||
boolean animatingX = isAnimating(view, TAG_ANIMATOR_TRANSLATION_X);
|
||||
if (animatingX) {
|
||||
updateAnimationX(view);
|
||||
} else if (view.getTranslationX() != this.xTranslation){
|
||||
view.setTranslationX(this.xTranslation);
|
||||
} else if (view.getTranslationX() != this.mXTranslation) {
|
||||
view.setTranslationX(this.mXTranslation);
|
||||
}
|
||||
|
||||
// apply yTranslation
|
||||
boolean animatingY = isAnimating(view, TAG_ANIMATOR_TRANSLATION_Y);
|
||||
if (animatingY) {
|
||||
updateAnimationY(view);
|
||||
} else if (view.getTranslationY() != this.yTranslation) {
|
||||
view.setTranslationY(this.yTranslation);
|
||||
} else if (view.getTranslationY() != this.mYTranslation) {
|
||||
view.setTranslationY(this.mYTranslation);
|
||||
}
|
||||
|
||||
// apply zTranslation
|
||||
boolean animatingZ = isAnimating(view, TAG_ANIMATOR_TRANSLATION_Z);
|
||||
if (animatingZ) {
|
||||
updateAnimationZ(view);
|
||||
} else if (view.getTranslationZ() != this.zTranslation) {
|
||||
view.setTranslationZ(this.zTranslation);
|
||||
} else if (view.getTranslationZ() != this.mZTranslation) {
|
||||
view.setTranslationZ(this.mZTranslation);
|
||||
}
|
||||
|
||||
// apply scaleX
|
||||
boolean animatingScaleX = isAnimating(view, SCALE_X_PROPERTY);
|
||||
if (animatingScaleX) {
|
||||
updateAnimation(view, SCALE_X_PROPERTY, scaleX);
|
||||
} else if (view.getScaleX() != scaleX) {
|
||||
view.setScaleX(scaleX);
|
||||
updateAnimation(view, SCALE_X_PROPERTY, mScaleX);
|
||||
} else if (view.getScaleX() != mScaleX) {
|
||||
view.setScaleX(mScaleX);
|
||||
}
|
||||
|
||||
// apply scaleY
|
||||
boolean animatingScaleY = isAnimating(view, SCALE_Y_PROPERTY);
|
||||
if (animatingScaleY) {
|
||||
updateAnimation(view, SCALE_Y_PROPERTY, scaleY);
|
||||
} else if (view.getScaleY() != scaleY) {
|
||||
view.setScaleY(scaleY);
|
||||
updateAnimation(view, SCALE_Y_PROPERTY, mScaleY);
|
||||
} else if (view.getScaleY() != mScaleY) {
|
||||
view.setScaleY(mScaleY);
|
||||
}
|
||||
|
||||
int oldVisibility = view.getVisibility();
|
||||
boolean becomesInvisible = this.alpha == 0.0f
|
||||
boolean becomesInvisible = this.mAlpha == 0.0f
|
||||
|| (this.hidden && (!isAnimating(view) || oldVisibility != View.VISIBLE));
|
||||
boolean animatingAlpha = isAnimating(view, TAG_ANIMATOR_ALPHA);
|
||||
if (animatingAlpha) {
|
||||
updateAlphaAnimation(view);
|
||||
} else if (view.getAlpha() != this.alpha) {
|
||||
} else if (view.getAlpha() != this.mAlpha) {
|
||||
// apply layer type
|
||||
boolean becomesFullyVisible = this.alpha == 1.0f;
|
||||
boolean becomesFullyVisible = this.mAlpha == 1.0f;
|
||||
boolean becomesFaded = !becomesInvisible && !becomesFullyVisible;
|
||||
if (FadeOptimizedNotification.FADE_LAYER_OPTIMIZATION_ENABLED
|
||||
&& view instanceof FadeOptimizedNotification) {
|
||||
@@ -229,7 +324,7 @@ public class ViewState implements Dumpable {
|
||||
}
|
||||
|
||||
// apply alpha
|
||||
view.setAlpha(this.alpha);
|
||||
view.setAlpha(this.mAlpha);
|
||||
}
|
||||
|
||||
// apply visibility
|
||||
@@ -274,54 +369,55 @@ public class ViewState implements Dumpable {
|
||||
|
||||
/**
|
||||
* Start an animation to this viewstate
|
||||
* @param child the view to animate
|
||||
*
|
||||
* @param child the view to animate
|
||||
* @param animationProperties the properties of the animation
|
||||
*/
|
||||
public void animateTo(View child, AnimationProperties animationProperties) {
|
||||
boolean wasVisible = child.getVisibility() == View.VISIBLE;
|
||||
final float alpha = this.alpha;
|
||||
final float alpha = this.mAlpha;
|
||||
if (!wasVisible && (alpha != 0 || child.getAlpha() != 0)
|
||||
&& !this.gone && !this.hidden) {
|
||||
child.setVisibility(View.VISIBLE);
|
||||
}
|
||||
float childAlpha = child.getAlpha();
|
||||
boolean alphaChanging = this.alpha != childAlpha;
|
||||
boolean alphaChanging = this.mAlpha != childAlpha;
|
||||
if (child instanceof ExpandableView) {
|
||||
// We don't want views to change visibility when they are animating to GONE
|
||||
alphaChanging &= !((ExpandableView) child).willBeGone();
|
||||
}
|
||||
|
||||
// start translationX animation
|
||||
if (child.getTranslationX() != this.xTranslation) {
|
||||
if (child.getTranslationX() != this.mXTranslation) {
|
||||
startXTranslationAnimation(child, animationProperties);
|
||||
} else {
|
||||
abortAnimation(child, TAG_ANIMATOR_TRANSLATION_X);
|
||||
}
|
||||
|
||||
// start translationY animation
|
||||
if (child.getTranslationY() != this.yTranslation) {
|
||||
if (child.getTranslationY() != this.mYTranslation) {
|
||||
startYTranslationAnimation(child, animationProperties);
|
||||
} else {
|
||||
abortAnimation(child, TAG_ANIMATOR_TRANSLATION_Y);
|
||||
}
|
||||
|
||||
// start translationZ animation
|
||||
if (child.getTranslationZ() != this.zTranslation) {
|
||||
if (child.getTranslationZ() != this.mZTranslation) {
|
||||
startZTranslationAnimation(child, animationProperties);
|
||||
} else {
|
||||
abortAnimation(child, TAG_ANIMATOR_TRANSLATION_Z);
|
||||
}
|
||||
|
||||
// start scaleX animation
|
||||
if (child.getScaleX() != scaleX) {
|
||||
PropertyAnimator.startAnimation(child, SCALE_X_PROPERTY, scaleX, animationProperties);
|
||||
if (child.getScaleX() != mScaleX) {
|
||||
PropertyAnimator.startAnimation(child, SCALE_X_PROPERTY, mScaleX, animationProperties);
|
||||
} else {
|
||||
abortAnimation(child, SCALE_X_PROPERTY.getAnimatorTag());
|
||||
}
|
||||
|
||||
// start scaleX animation
|
||||
if (child.getScaleY() != scaleY) {
|
||||
PropertyAnimator.startAnimation(child, SCALE_Y_PROPERTY, scaleY, animationProperties);
|
||||
if (child.getScaleY() != mScaleY) {
|
||||
PropertyAnimator.startAnimation(child, SCALE_Y_PROPERTY, mScaleY, animationProperties);
|
||||
} else {
|
||||
abortAnimation(child, SCALE_Y_PROPERTY.getAnimatorTag());
|
||||
}
|
||||
@@ -329,7 +425,7 @@ public class ViewState implements Dumpable {
|
||||
// start alpha animation
|
||||
if (alphaChanging) {
|
||||
startAlphaAnimation(child, animationProperties);
|
||||
} else {
|
||||
} else {
|
||||
abortAnimation(child, TAG_ANIMATOR_ALPHA);
|
||||
}
|
||||
}
|
||||
@@ -339,9 +435,9 @@ public class ViewState implements Dumpable {
|
||||
}
|
||||
|
||||
private void startAlphaAnimation(final View child, AnimationProperties properties) {
|
||||
Float previousStartValue = getChildTag(child,TAG_START_ALPHA);
|
||||
Float previousEndValue = getChildTag(child,TAG_END_ALPHA);
|
||||
final float newEndValue = this.alpha;
|
||||
Float previousStartValue = getChildTag(child, TAG_START_ALPHA);
|
||||
Float previousEndValue = getChildTag(child, TAG_END_ALPHA);
|
||||
final float newEndValue = this.mAlpha;
|
||||
if (previousEndValue != null && previousEndValue == newEndValue) {
|
||||
return;
|
||||
}
|
||||
@@ -426,9 +522,9 @@ public class ViewState implements Dumpable {
|
||||
}
|
||||
|
||||
private void startZTranslationAnimation(final View child, AnimationProperties properties) {
|
||||
Float previousStartValue = getChildTag(child,TAG_START_TRANSLATION_Z);
|
||||
Float previousEndValue = getChildTag(child,TAG_END_TRANSLATION_Z);
|
||||
float newEndValue = this.zTranslation;
|
||||
Float previousStartValue = getChildTag(child, TAG_START_TRANSLATION_Z);
|
||||
Float previousEndValue = getChildTag(child, TAG_END_TRANSLATION_Z);
|
||||
float newEndValue = this.mZTranslation;
|
||||
if (previousEndValue != null && previousEndValue == newEndValue) {
|
||||
return;
|
||||
}
|
||||
@@ -487,9 +583,9 @@ public class ViewState implements Dumpable {
|
||||
}
|
||||
|
||||
private void startXTranslationAnimation(final View child, AnimationProperties properties) {
|
||||
Float previousStartValue = getChildTag(child,TAG_START_TRANSLATION_X);
|
||||
Float previousEndValue = getChildTag(child,TAG_END_TRANSLATION_X);
|
||||
float newEndValue = this.xTranslation;
|
||||
Float previousStartValue = getChildTag(child, TAG_START_TRANSLATION_X);
|
||||
Float previousEndValue = getChildTag(child, TAG_END_TRANSLATION_X);
|
||||
float newEndValue = this.mXTranslation;
|
||||
if (previousEndValue != null && previousEndValue == newEndValue) {
|
||||
return;
|
||||
}
|
||||
@@ -519,7 +615,7 @@ public class ViewState implements Dumpable {
|
||||
child.getTranslationX(), newEndValue);
|
||||
Interpolator customInterpolator = properties.getCustomInterpolator(child,
|
||||
View.TRANSLATION_X);
|
||||
Interpolator interpolator = customInterpolator != null ? customInterpolator
|
||||
Interpolator interpolator = customInterpolator != null ? customInterpolator
|
||||
: Interpolators.FAST_OUT_SLOW_IN;
|
||||
animator.setInterpolator(interpolator);
|
||||
long newDuration = cancelAnimatorAndGetNewDuration(properties.duration, previousAnimator);
|
||||
@@ -553,9 +649,9 @@ public class ViewState implements Dumpable {
|
||||
}
|
||||
|
||||
private void startYTranslationAnimation(final View child, AnimationProperties properties) {
|
||||
Float previousStartValue = getChildTag(child,TAG_START_TRANSLATION_Y);
|
||||
Float previousEndValue = getChildTag(child,TAG_END_TRANSLATION_Y);
|
||||
float newEndValue = this.yTranslation;
|
||||
Float previousStartValue = getChildTag(child, TAG_START_TRANSLATION_Y);
|
||||
Float previousEndValue = getChildTag(child, TAG_END_TRANSLATION_Y);
|
||||
float newEndValue = this.mYTranslation;
|
||||
if (previousEndValue != null && previousEndValue == newEndValue) {
|
||||
return;
|
||||
}
|
||||
@@ -585,7 +681,7 @@ public class ViewState implements Dumpable {
|
||||
child.getTranslationY(), newEndValue);
|
||||
Interpolator customInterpolator = properties.getCustomInterpolator(child,
|
||||
View.TRANSLATION_Y);
|
||||
Interpolator interpolator = customInterpolator != null ? customInterpolator
|
||||
Interpolator interpolator = customInterpolator != null ? customInterpolator
|
||||
: Interpolators.FAST_OUT_SLOW_IN;
|
||||
animator.setInterpolator(interpolator);
|
||||
long newDuration = cancelAnimatorAndGetNewDuration(properties.duration, previousAnimator);
|
||||
@@ -644,7 +740,7 @@ public class ViewState implements Dumpable {
|
||||
/**
|
||||
* Cancel the previous animator and get the duration of the new animation.
|
||||
*
|
||||
* @param duration the new duration
|
||||
* @param duration the new duration
|
||||
* @param previousAnimator the animator which was running before
|
||||
* @return the new duration
|
||||
*/
|
||||
|
||||
@@ -211,11 +211,11 @@ public class NotificationIconContainer extends ViewGroup {
|
||||
canvas.drawLine(end, 0, end, height, paint);
|
||||
|
||||
paint.setColor(Color.GREEN);
|
||||
int lastIcon = (int) mLastVisibleIconState.xTranslation;
|
||||
int lastIcon = (int) mLastVisibleIconState.getXTranslation();
|
||||
canvas.drawLine(lastIcon, 0, lastIcon, height, paint);
|
||||
|
||||
if (mFirstVisibleIconState != null) {
|
||||
int firstIcon = (int) mFirstVisibleIconState.xTranslation;
|
||||
int firstIcon = (int) mFirstVisibleIconState.getXTranslation();
|
||||
canvas.drawLine(firstIcon, 0, firstIcon, height, paint);
|
||||
}
|
||||
|
||||
@@ -413,7 +413,7 @@ public class NotificationIconContainer extends ViewGroup {
|
||||
View view = getChildAt(i);
|
||||
ViewState iconState = mIconStates.get(view);
|
||||
iconState.initFrom(view);
|
||||
iconState.alpha = mIsolatedIcon == null || view == mIsolatedIcon ? 1.0f : 0.0f;
|
||||
iconState.setAlpha(mIsolatedIcon == null || view == mIsolatedIcon ? 1.0f : 0.0f);
|
||||
iconState.hidden = false;
|
||||
}
|
||||
}
|
||||
@@ -467,7 +467,7 @@ public class NotificationIconContainer extends ViewGroup {
|
||||
// We only modify the xTranslation if it's fully inside of the container
|
||||
// since during the transition to the shelf, the translations are controlled
|
||||
// from the outside
|
||||
iconState.xTranslation = translationX;
|
||||
iconState.setXTranslation(translationX);
|
||||
}
|
||||
if (mFirstVisibleIconState == null) {
|
||||
mFirstVisibleIconState = iconState;
|
||||
@@ -501,7 +501,7 @@ public class NotificationIconContainer extends ViewGroup {
|
||||
View view = getChildAt(i);
|
||||
IconState iconState = mIconStates.get(view);
|
||||
int dotWidth = mStaticDotDiameter + mDotPadding;
|
||||
iconState.xTranslation = translationX;
|
||||
iconState.setXTranslation(translationX);
|
||||
if (mNumDots < MAX_DOTS) {
|
||||
if (mNumDots == 0 && iconState.iconAppearAmount < 0.8f) {
|
||||
iconState.visibleState = StatusBarIconView.STATE_ICON;
|
||||
@@ -525,7 +525,8 @@ public class NotificationIconContainer extends ViewGroup {
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
View view = getChildAt(i);
|
||||
IconState iconState = mIconStates.get(view);
|
||||
iconState.xTranslation = getWidth() - iconState.xTranslation - view.getWidth();
|
||||
iconState.setXTranslation(
|
||||
getWidth() - iconState.getXTranslation() - view.getWidth());
|
||||
}
|
||||
}
|
||||
if (mIsolatedIcon != null) {
|
||||
@@ -533,8 +534,8 @@ public class NotificationIconContainer extends ViewGroup {
|
||||
if (iconState != null) {
|
||||
// Most of the time the icon isn't yet added when this is called but only happening
|
||||
// later
|
||||
iconState.xTranslation = mIsolatedIconLocation.left - mAbsolutePosition[0]
|
||||
- (1 - mIsolatedIcon.getIconScale()) * mIsolatedIcon.getWidth() / 2.0f;
|
||||
iconState.setXTranslation(mIsolatedIconLocation.left - mAbsolutePosition[0]
|
||||
- (1 - mIsolatedIcon.getIconScale()) * mIsolatedIcon.getWidth() / 2.0f);
|
||||
iconState.visibleState = StatusBarIconView.STATE_ICON;
|
||||
}
|
||||
}
|
||||
@@ -609,8 +610,10 @@ public class NotificationIconContainer extends ViewGroup {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int translation = (int) (isLayoutRtl() ? getWidth() - mLastVisibleIconState.xTranslation
|
||||
: mLastVisibleIconState.xTranslation + mIconSize);
|
||||
int translation = (int) (isLayoutRtl()
|
||||
? getWidth() - mLastVisibleIconState.getXTranslation()
|
||||
: mLastVisibleIconState.getXTranslation() + mIconSize);
|
||||
|
||||
// There's a chance that last translation goes beyond the edge maybe
|
||||
return Math.min(getWidth(), translation);
|
||||
}
|
||||
|
||||
@@ -337,7 +337,7 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
|
||||
// without cutting off the child view.
|
||||
translationX -= getViewTotalWidth(child);
|
||||
childState.visibleState = STATE_ICON;
|
||||
childState.xTranslation = translationX;
|
||||
childState.setXTranslation(translationX);
|
||||
mLayoutStates.add(0, childState);
|
||||
|
||||
// Shift translationX over by mIconSpacing for the next view.
|
||||
@@ -354,13 +354,13 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
|
||||
for (int i = totalVisible - 1; i >= 0; i--) {
|
||||
StatusIconState state = mLayoutStates.get(i);
|
||||
// Allow room for underflow if we found we need it in onMeasure
|
||||
if (mNeedsUnderflow && (state.xTranslation < (contentStart + mUnderflowWidth))||
|
||||
(mShouldRestrictIcons && visible >= maxVisible)) {
|
||||
if (mNeedsUnderflow && (state.getXTranslation() < (contentStart + mUnderflowWidth))
|
||||
|| (mShouldRestrictIcons && (visible >= maxVisible))) {
|
||||
firstUnderflowIndex = i;
|
||||
break;
|
||||
}
|
||||
mUnderflowStart = (int) Math.max(
|
||||
contentStart, state.xTranslation - mUnderflowWidth - mIconSpacing);
|
||||
contentStart, state.getXTranslation() - mUnderflowWidth - mIconSpacing);
|
||||
visible++;
|
||||
}
|
||||
|
||||
@@ -371,7 +371,7 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
|
||||
for (int i = firstUnderflowIndex; i >= 0; i--) {
|
||||
StatusIconState state = mLayoutStates.get(i);
|
||||
if (totalDots < MAX_DOTS) {
|
||||
state.xTranslation = dotOffset;
|
||||
state.setXTranslation(dotOffset);
|
||||
state.visibleState = STATE_DOT;
|
||||
dotOffset -= dotWidth;
|
||||
totalDots++;
|
||||
@@ -386,7 +386,7 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
View child = getChildAt(i);
|
||||
StatusIconState state = getViewStateFromChild(child);
|
||||
state.xTranslation = width - state.xTranslation - child.getWidth();
|
||||
state.setXTranslation(width - state.getXTranslation() - child.getWidth());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -410,7 +410,7 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
|
||||
}
|
||||
|
||||
vs.initFrom(child);
|
||||
vs.alpha = 1.0f;
|
||||
vs.setAlpha(1.0f);
|
||||
vs.hidden = false;
|
||||
}
|
||||
}
|
||||
@@ -442,7 +442,7 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
|
||||
parentWidth = ((View) view.getParent()).getWidth();
|
||||
}
|
||||
|
||||
float currentDistanceToEnd = parentWidth - xTranslation;
|
||||
float currentDistanceToEnd = parentWidth - getXTranslation();
|
||||
|
||||
if (!(view instanceof StatusIconDisplayable)) {
|
||||
return;
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package com.android.systemui.statusbar.notification.stack
|
||||
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.util.Log
|
||||
import android.util.Log.TerribleFailureHandler
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import kotlin.math.log2
|
||||
import kotlin.math.sqrt
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
@SmallTest
|
||||
class ViewStateTest : SysuiTestCase() {
|
||||
private val viewState = ViewState()
|
||||
|
||||
private var wtfHandler: TerribleFailureHandler? = null
|
||||
private var wtfCount = 0
|
||||
|
||||
@Suppress("DIVISION_BY_ZERO")
|
||||
@Test
|
||||
fun testWtfs() {
|
||||
interceptWtfs()
|
||||
|
||||
// Setting valid values doesn't cause any wtfs.
|
||||
viewState.alpha = 0.1f
|
||||
viewState.xTranslation = 0f
|
||||
viewState.yTranslation = 10f
|
||||
viewState.zTranslation = 20f
|
||||
viewState.scaleX = 0.5f
|
||||
viewState.scaleY = 0.25f
|
||||
|
||||
expectWtfs(0)
|
||||
|
||||
// Setting NaN values leads to wtfs being logged, and the value not being changed.
|
||||
viewState.alpha = 0.0f / 0.0f
|
||||
expectWtfs(1)
|
||||
Assert.assertEquals(viewState.alpha, 0.1f)
|
||||
|
||||
viewState.xTranslation = Float.NaN
|
||||
expectWtfs(2)
|
||||
Assert.assertEquals(viewState.xTranslation, 0f)
|
||||
|
||||
viewState.yTranslation = log2(-10.0).toFloat()
|
||||
expectWtfs(3)
|
||||
Assert.assertEquals(viewState.yTranslation, 10f)
|
||||
|
||||
viewState.zTranslation = sqrt(-1.0).toFloat()
|
||||
expectWtfs(4)
|
||||
Assert.assertEquals(viewState.zTranslation, 20f)
|
||||
|
||||
viewState.scaleX = Float.POSITIVE_INFINITY + Float.NEGATIVE_INFINITY
|
||||
expectWtfs(5)
|
||||
Assert.assertEquals(viewState.scaleX, 0.5f)
|
||||
|
||||
viewState.scaleY = Float.POSITIVE_INFINITY * 0
|
||||
expectWtfs(6)
|
||||
Assert.assertEquals(viewState.scaleY, 0.25f)
|
||||
}
|
||||
|
||||
private fun interceptWtfs() {
|
||||
wtfCount = 0
|
||||
wtfHandler =
|
||||
Log.setWtfHandler { _: String?, e: Log.TerribleFailure, _: Boolean ->
|
||||
Log.e("ViewStateTest", "Observed WTF: $e")
|
||||
wtfCount++
|
||||
}
|
||||
}
|
||||
|
||||
private fun expectWtfs(expectedWtfCount: Int) {
|
||||
Assert.assertNotNull(wtfHandler)
|
||||
Assert.assertEquals(expectedWtfCount, wtfCount)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user