From d2ad623032021187848a945c60bff8a830f5f092 Mon Sep 17 00:00:00 2001 From: Selim Cinek Date: Mon, 7 Jun 2021 20:02:10 +0200 Subject: [PATCH] Tuned the heads up animations more The previous animation was using the linear interpolator for the shape change, which is now properly using the existing interpolator. Also the roundedness is now using the interpolator to feel more connected to the rest of the animation. This also fixes some bugs where the heads up was animating it's corner roundedness immediately, before it was decided whether we will animating away, leading to some issues. Lastly, this also adds a failsafe for the roundedness, which could become really large if the roundness was updated without an animation, while an animation was running already. Fixes: 187175147 Test: add hun, observe nice animation Change-Id: I4561eed97387e3465e7ea61066bffa11d8e6bda0 --- .../row/ActivatableNotificationView.java | 42 ++++++--------- .../row/ExpandableOutlineView.java | 22 +++++++- .../stack/HeadsUpAppearInterpolator.java | 52 ------------------- .../stack/NotificationRoundnessManager.java | 3 +- ...tificationStackScrollLayoutController.java | 12 +++-- .../stack/StackStateAnimator.java | 20 ++----- .../NotificationPanelViewController.java | 5 -- 7 files changed, 50 insertions(+), 106 deletions(-) delete mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/HeadsUpAppearInterpolator.java diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java index b18f191c4333a..413662447028c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java @@ -60,12 +60,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView */ private static final float HORIZONTAL_ANIMATION_END = 0.2f; - /** - * At which point from [0,1] does the alpha animation end (or start when - * expanding)? 1.0 meaning that it ends immediately and 0.0 that it is continuously animated. - */ - private static final float ALPHA_ANIMATION_END = 0.0f; - /** * At which point from [0,1] does the horizontal collapse animation start (or start when * expanding)? 1.0 meaning that it starts immediately and 0.0 that it is animated at all. @@ -497,10 +491,10 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView float targetValue; if (isAppearing) { - mCurrentAppearInterpolator = mSlowOutFastInInterpolator; + mCurrentAppearInterpolator = Interpolators.FAST_OUT_SLOW_IN; targetValue = 1.0f; } else { - mCurrentAppearInterpolator = Interpolators.FAST_OUT_SLOW_IN; + mCurrentAppearInterpolator = mSlowOutFastInInterpolator; targetValue = 0.0f; } mAppearAnimator = ValueAnimator.ofFloat(mAppearAnimationFraction, @@ -584,19 +578,21 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView } private void updateAppearRect() { - float inverseFraction = (1.0f - mAppearAnimationFraction); - float translationFraction = mCurrentAppearInterpolator.getInterpolation(inverseFraction); - float translateYTotalAmount = translationFraction * mAnimationTranslationY; - mAppearAnimationTranslation = translateYTotalAmount; + float interpolatedFraction = mCurrentAppearInterpolator.getInterpolation( + mAppearAnimationFraction); + mAppearAnimationTranslation = (1.0f - interpolatedFraction) * mAnimationTranslationY; final int actualHeight = getActualHeight(); - float bottom = actualHeight * mAppearAnimationFraction; + float bottom = actualHeight * interpolatedFraction; - setOutlineRect(0, mAppearAnimationTranslation, - getWidth(), bottom + mAppearAnimationTranslation); + setOutlineRect(0, mAppearAnimationTranslation, getWidth(), + bottom + mAppearAnimationTranslation); } - private float getAppearAnimationFraction() { - return mAppearAnimationFraction >= 0 ? mAppearAnimationFraction : 1; + private float getInterpolatedAppearAnimationFraction() { + if (mAppearAnimationFraction >= 0) { + return mCurrentAppearInterpolator.getInterpolation(mAppearAnimationFraction); + } + return 1.0f; } private void updateAppearAnimationAlpha() { @@ -629,18 +625,14 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView @Override public float getCurrentBackgroundRadiusTop() { - float fraction = getAppearAnimationFraction(); - return isHeadsUpAnimatingAway() || isHeadsUp() - ? mOutlineRadius * fraction - : super.getCurrentBackgroundRadiusTop(); + float fraction = getInterpolatedAppearAnimationFraction(); + return MathUtils.lerp(0, super.getCurrentBackgroundRadiusTop(), fraction); } @Override public float getCurrentBackgroundRadiusBottom() { - float fraction = getAppearAnimationFraction(); - return isHeadsUpAnimatingAway() || isHeadsUp() - ? mOutlineRadius * fraction - : super.getCurrentBackgroundRadiusBottom(); + float fraction = getInterpolatedAppearAnimationFraction(); + return MathUtils.lerp(0, super.getCurrentBackgroundRadiusBottom(), fraction); } private void applyBackgroundRoundness(float topRadius, float bottomRadius) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java index 3728388f63b26..5134c62dc1820 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java @@ -249,9 +249,18 @@ public abstract class ExpandableOutlineView extends ExpandableView { @Override public boolean setTopRoundness(float topRoundness, boolean animate) { if (mTopRoundness != topRoundness) { + float diff = Math.abs(topRoundness - mTopRoundness); mTopRoundness = topRoundness; + boolean shouldAnimate = animate; + if (PropertyAnimator.isAnimating(this, TOP_ROUNDNESS) && diff > 0.5f) { + // Fail safe: + // when we've been animating previously and we're now getting an update in the + // other direction, make sure to animate it too, otherwise, the localized updating + // may make the start larger than 1.0. + shouldAnimate = true; + } PropertyAnimator.setProperty(this, TOP_ROUNDNESS, topRoundness, - ROUNDNESS_PROPERTIES, animate); + ROUNDNESS_PROPERTIES, shouldAnimate); return true; } return false; @@ -286,9 +295,18 @@ public abstract class ExpandableOutlineView extends ExpandableView { @Override public boolean setBottomRoundness(float bottomRoundness, boolean animate) { if (mBottomRoundness != bottomRoundness) { + float diff = Math.abs(bottomRoundness - mBottomRoundness); mBottomRoundness = bottomRoundness; + boolean shouldAnimate = animate; + if (PropertyAnimator.isAnimating(this, BOTTOM_ROUNDNESS) && diff > 0.5f) { + // Fail safe: + // when we've been animating previously and we're now getting an update in the + // other direction, make sure to animate it too, otherwise, the localized updating + // may make the start larger than 1.0. + shouldAnimate = true; + } PropertyAnimator.setProperty(this, BOTTOM_ROUNDNESS, bottomRoundness, - ROUNDNESS_PROPERTIES, animate); + ROUNDNESS_PROPERTIES, shouldAnimate); return true; } return false; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/HeadsUpAppearInterpolator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/HeadsUpAppearInterpolator.java deleted file mode 100644 index 24e1f32397204..0000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/HeadsUpAppearInterpolator.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2015 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.graphics.Path; -import android.view.animation.PathInterpolator; - -/** - * An interpolator specifically designed for the appear animation of heads up notifications. - */ -public class HeadsUpAppearInterpolator extends PathInterpolator { - - private static float X1 = 250f; - private static float X2 = 200f; - private static float XTOT = (X1 + X2);; - - public HeadsUpAppearInterpolator() { - super(getAppearPath()); - } - - private static Path getAppearPath() { - Path path = new Path(); - path.moveTo(0, 0); - float y1 = 90f; - float y2 = 80f; - path.cubicTo(X1 * 0.8f / XTOT, y1 / y2, - X1 * 0.8f / XTOT, y1 / y2, - X1 / XTOT, y1 / y2); - path.cubicTo((X1 + X2 * 0.4f) / XTOT, y1 / y2, - (X1 + X2 * 0.2f) / XTOT, 1.0f, - 1.0f , 1.0f); - return path; - } - - public static float getFractionUntilOvershoot() { - return X1 / XTOT; - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java index 4b49e3a90ede1..23aefd9bfd8e4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java @@ -18,7 +18,6 @@ package com.android.systemui.statusbar.notification.stack; import android.content.res.Resources; import android.util.MathUtils; -import android.view.View; import com.android.systemui.R; import com.android.systemui.dagger.SysUISingleton; @@ -199,7 +198,7 @@ public class NotificationRoundnessManager { mExpanded = expandedHeight != 0.0f; mAppearFraction = appearFraction; if (mTrackedHeadsUp != null) { - updateView(mTrackedHeadsUp, true); + updateView(mTrackedHeadsUp, false /* animate */); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java index 4432f5463802e..7e423c35a5dcf 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java @@ -544,7 +544,11 @@ public class NotificationStackScrollLayoutController { @Override public void onHeadsUpUnPinned(NotificationEntry entry) { - mNotificationRoundnessManager.updateView(entry.getRow(), true /* animate */); + ExpandableNotificationRow row = entry.getRow(); + // update the roundedness posted, because we might be animating away the + // headsup soon, so no need to set the roundedness to 0 and then back to 1. + row.post(() -> mNotificationRoundnessManager.updateView(row, + true /* animate */)); } @Override @@ -553,7 +557,9 @@ public class NotificationStackScrollLayoutController { NotificationEntry topEntry = mHeadsUpManager.getTopEntry(); mView.setNumHeadsUp(numEntries); mView.setTopHeadsUpEntry(topEntry); - mNotificationRoundnessManager.updateView(entry.getRow(), false /* animate */); + generateHeadsUpAnimation(entry, isHeadsUp); + ExpandableNotificationRow row = entry.getRow(); + mNotificationRoundnessManager.updateView(row, true /* animate */); } }; @@ -1238,7 +1244,7 @@ public class NotificationStackScrollLayoutController { return mView.getFirstChildNotGone(); } - public void generateHeadsUpAnimation(NotificationEntry entry, boolean isHeadsUp) { + private void generateHeadsUpAnimation(NotificationEntry entry, boolean isHeadsUp) { mView.generateHeadsUpAnimation(entry, isHeadsUp); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java index 83dc6df5415a4..4fd2064b394d1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java @@ -21,7 +21,6 @@ import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.util.Property; import android.view.View; -import android.view.animation.Interpolator; import com.android.keyguard.KeyguardSliceView; import com.android.systemui.R; @@ -50,11 +49,8 @@ public class StackStateAnimator { public static final int ANIMATION_DURATION_SWIPE = 260; public static final int ANIMATION_DURATION_DIMMED_ACTIVATED = 220; public static final int ANIMATION_DURATION_CLOSE_REMOTE_INPUT = 150; - public static final int ANIMATION_DURATION_HEADS_UP_APPEAR = 550; - public static final int ANIMATION_DURATION_HEADS_UP_APPEAR_CLOSED - = (int) (ANIMATION_DURATION_HEADS_UP_APPEAR - * HeadsUpAppearInterpolator.getFractionUntilOvershoot()); - public static final int ANIMATION_DURATION_HEADS_UP_DISAPPEAR = 300; + public static final int ANIMATION_DURATION_HEADS_UP_APPEAR = 400; + public static final int ANIMATION_DURATION_HEADS_UP_DISAPPEAR = 400; public static final int ANIMATION_DURATION_PULSE_APPEAR = KeyguardSliceView.DEFAULT_ANIM_DURATION; public static final int ANIMATION_DURATION_BLOCKING_HELPER_FADE = 240; @@ -64,8 +60,6 @@ public class StackStateAnimator { public static final int ANIMATION_DELAY_PER_ELEMENT_GO_TO_FULL_SHADE = 48; public static final int DELAY_EFFECT_MAX_INDEX_DIFFERENCE = 2; private static final int MAX_STAGGER_COUNT = 5; - private static final HeadsUpAppearInterpolator HEADS_UP_APPEAR_INTERPOLATOR = - new HeadsUpAppearInterpolator(); private final int mGoToFullShadeAppearingTranslation; private final int mPulsingAppearingTranslation; @@ -115,14 +109,6 @@ public class StackStateAnimator { public boolean wasAdded(View view) { return mNewAddChildren.contains(view); } - - @Override - public Interpolator getCustomInterpolator(View child, Property property) { - if (mHeadsUpAppearChildren.contains(child) && View.TRANSLATION_Y.equals(property)) { - return HEADS_UP_APPEAR_INTERPOLATOR; - } - return null; - } }; } @@ -422,7 +408,7 @@ public class StackStateAnimator { if (event.headsUpFromBottom) { mTmpState.yTranslation = mHeadsUpAppearHeightBottom; } else { - changingView.performAddAnimation(0, ANIMATION_DURATION_HEADS_UP_APPEAR_CLOSED, + changingView.performAddAnimation(0, ANIMATION_DURATION_HEADS_UP_APPEAR, true /* isHeadsUpAppear */); } mHeadsUpAppearChildren.add(changingView); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index dc71c10ed87cf..80478172859a9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -4182,11 +4182,6 @@ public class NotificationPanelViewController extends PanelViewController { entry.setHeadsUpIsVisible(); } } - - @Override - public void onHeadsUpStateChanged(NotificationEntry entry, boolean isHeadsUp) { - mNotificationStackScrollLayoutController.generateHeadsUpAnimation(entry, isHeadsUp); - } } private class HeightListener implements QS.HeightListener {