From d9b7dd4a5dd89d5fdaf0e5aee43d052f8958b4d2 Mon Sep 17 00:00:00 2001 From: Selim Cinek Date: Fri, 10 Nov 2017 17:53:47 -0800 Subject: [PATCH] Implemented animations for rounding The corners now animate nicely instead of just jumping. Bug: 69168591 Test: manual, swipe away notifications Change-Id: Ia45774b1fed4d7b0a5cf2ec56ff1560ff685503c --- packages/SystemUI/res/values/ids.xml | 8 ++ .../ActivatableNotificationView.java | 3 +- .../statusbar/ExpandableNotificationRow.java | 1 + .../statusbar/ExpandableOutlineView.java | 82 ++++++++++++++----- .../systemui/statusbar/ExpandableView.java | 4 + .../systemui/statusbar/NotificationShelf.java | 6 +- .../stack/NotificationStackScrollLayout.java | 28 +++++-- 7 files changed, 100 insertions(+), 32 deletions(-) diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml index cfd95b41825a6..d491df3dae428 100644 --- a/packages/SystemUI/res/values/ids.xml +++ b/packages/SystemUI/res/values/ids.xml @@ -77,6 +77,14 @@ + + + + + + + + diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java index 668d4699f9eff..06bee433dad5d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java @@ -904,7 +904,8 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView @Override protected void applyRoundness() { super.applyRoundness(); - applyBackgroundRoundness(getBackgroundRadiusTop(), getBackgroundRadiusBottom()); + applyBackgroundRoundness(getCurrentBackgroundRadiusTop(), + getCurrentBackgroundRadiusBottom()); } protected void applyBackgroundRoundness(float topRadius, float bottomRadius) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java index ccbc6a3932b8a..82d42e59d3211 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java @@ -1025,6 +1025,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mKeepInParent = keepInParent; } + @Override public boolean isRemoved() { return mRemoved; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java index abd6f206db712..14ffb42a3ec91 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java @@ -29,12 +29,33 @@ import android.view.ViewOutlineProvider; import com.android.settingslib.Utils; import com.android.systemui.R; +import com.android.systemui.statusbar.notification.AnimatableProperty; +import com.android.systemui.statusbar.notification.PropertyAnimator; +import com.android.systemui.statusbar.stack.AnimationProperties; +import com.android.systemui.statusbar.stack.StackStateAnimator; /** * Like {@link ExpandableView}, but setting an outline for the height and clipping. */ public abstract class ExpandableOutlineView extends ExpandableView { + private static final AnimatableProperty TOP_ROUNDNESS = AnimatableProperty.from( + "topRoundness", + ExpandableOutlineView::setTopRoundnessInternal, + ExpandableOutlineView::getCurrentTopRoundness, + R.id.top_roundess_animator_tag, + R.id.top_roundess_animator_end_tag, + R.id.top_roundess_animator_start_tag); + private static final AnimatableProperty BOTTOM_ROUNDNESS = AnimatableProperty.from( + "bottomRoundness", + ExpandableOutlineView::setBottomRoundnessInternal, + ExpandableOutlineView::getCurrentBottomRoundness, + R.id.bottom_roundess_animator_tag, + R.id.bottom_roundess_animator_end_tag, + R.id.bottom_roundess_animator_start_tag); + private static final AnimationProperties ROUNDNESS_PROPERTIES = + new AnimationProperties().setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD); + private final Rect mOutlineRect = new Rect(); private boolean mCustomOutline; private float mOutlineAlpha = -1f; @@ -42,8 +63,10 @@ public abstract class ExpandableOutlineView extends ExpandableView { private boolean mAlwaysRoundBothCorners; private Path mTmpPath = new Path(); private Path mTmpPath2 = new Path(); + private float mCurrentBottomRoundness; + private float mCurrentTopRoundness; + private float mBottomRoundness; private float mTopRoundness; - private float mBottomRoundNess; /** * {@code true} if the children views of the {@link ExpandableOutlineView} are translated when @@ -94,15 +117,15 @@ public abstract class ExpandableOutlineView extends ExpandableView { return null; } float topRoundness = mAlwaysRoundBothCorners - ? mOutlineRadius : mTopRoundness * mOutlineRadius; + ? mOutlineRadius : mCurrentTopRoundness * mOutlineRadius; float bottomRoundness = mAlwaysRoundBothCorners - ? mOutlineRadius : mBottomRoundNess * mOutlineRadius; + ? mOutlineRadius : mCurrentBottomRoundness * mOutlineRadius; if (topRoundness + bottomRoundness > height) { float overShoot = topRoundness + bottomRoundness - height; - topRoundness -= overShoot * mTopRoundness - / (mTopRoundness + mBottomRoundNess); - bottomRoundness -= overShoot * mBottomRoundNess - / (mTopRoundness + mBottomRoundNess); + topRoundness -= overShoot * mCurrentTopRoundness + / (mCurrentTopRoundness + mCurrentBottomRoundness); + bottomRoundness -= overShoot * mCurrentBottomRoundness + / (mCurrentTopRoundness + mCurrentBottomRoundness); } getRoundedRectPath(left, top, right, bottom, topRoundness, bottomRoundness, mTmpPath); @@ -158,8 +181,8 @@ public abstract class ExpandableOutlineView extends ExpandableView { @Override protected void dispatchDraw(Canvas canvas) { canvas.save(); - if (needsContentClipping() && (mAlwaysRoundBothCorners || mTopRoundness > 0 - || mBottomRoundNess > 0 || mCustomOutline)) { + if (needsContentClipping() && (mAlwaysRoundBothCorners || mCurrentTopRoundness > 0 + || mCurrentBottomRoundness > 0 || mCustomOutline)) { Path clipPath = getCustomClipPath(); if (clipPath == null) { clipPath = getClipPath(); @@ -189,10 +212,11 @@ public abstract class ExpandableOutlineView extends ExpandableView { setClipToOutline(mAlwaysRoundBothCorners); } - public void setTopRoundness(float topRoundness) { + public void setTopRoundness(float topRoundness, boolean animate) { if (mTopRoundness != topRoundness) { mTopRoundness = topRoundness; - applyRoundness(); + PropertyAnimator.setProperty(this, TOP_ROUNDNESS, topRoundness, + ROUNDNESS_PROPERTIES, animate); } } @@ -201,25 +225,41 @@ public abstract class ExpandableOutlineView extends ExpandableView { invalidate(); } - protected float getBackgroundRadiusTop() { - return mTopRoundness * mOutlineRadius; + protected float getCurrentBackgroundRadiusTop() { + return mCurrentTopRoundness * mOutlineRadius; } - protected float getTopRoundness() { - return mTopRoundness; + protected float getCurrentTopRoundness() { + return mCurrentTopRoundness; } - protected float getBackgroundRadiusBottom() { - return mBottomRoundNess * mOutlineRadius; + protected float getCurrentBottomRoundness() { + return mCurrentBottomRoundness; } - public void setBottomRoundNess(float bottomRoundness) { - if (mBottomRoundNess != bottomRoundness) { - mBottomRoundNess = bottomRoundness; - applyRoundness(); + protected float getCurrentBackgroundRadiusBottom() { + return mCurrentBottomRoundness * mOutlineRadius; + } + + public void setBottomRoundNess(float bottomRoundness, boolean animate) { + if (mBottomRoundness != bottomRoundness) { + mBottomRoundness = bottomRoundness; + PropertyAnimator.setProperty(this, BOTTOM_ROUNDNESS, bottomRoundness, + ROUNDNESS_PROPERTIES, animate); } } + + private void setTopRoundnessInternal(float topRoundness) { + mCurrentTopRoundness = topRoundness; + applyRoundness(); + } + + private void setBottomRoundnessInternal(float bottomRoundness) { + mCurrentBottomRoundness = bottomRoundness; + applyRoundness(); + } + public void onDensityOrFontScaleChanged() { initDimens(); applyRoundness(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java index aac9af8a0234e..18b986027a4ac 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java @@ -202,6 +202,10 @@ public abstract class ExpandableView extends FrameLayout { return mDark; } + public boolean isRemoved() { + return false; + } + /** * See {@link #setHideSensitive}. This is a variant which notifies this view in advance about * the upcoming state of hiding sensitive notifications. It gets called at the very beginning diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java index d15fe6919236d..5911a3df6e358 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java @@ -111,7 +111,7 @@ public class NotificationShelf extends ActivatableNotificationView implements mViewInvertHelper = new ViewInvertHelper(mShelfIcons, NotificationPanelView.DOZE_ANIMATION_DURATION); mShelfState = new ShelfState(); - setBottomRoundNess(1.0f); + setBottomRoundNess(1.0f, false /* animate */); initDimens(); } @@ -314,7 +314,7 @@ public class NotificationShelf extends ActivatableNotificationView implements if (iconState.clampedAppearAmount == 1.0f) { // only if the first icon is fully in the shelf we want to clip to it! mCustomClipTop = (int) (row.getTranslationY() - getTranslationY()); - mFirstElementTopRoundness = row.getBackgroundRadiusTop(); + mFirstElementTopRoundness = row.getCurrentBackgroundRadiusTop(); contentNeedsClipping = true; } } @@ -356,7 +356,7 @@ public class NotificationShelf extends ActivatableNotificationView implements return null; } return getRoundedRectPath(0, mCustomClipTop, getWidth(), getHeight(), - mFirstElementTopRoundness, getBackgroundRadiusBottom()); + mFirstElementTopRoundness, getCurrentBackgroundRadiusBottom()); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java index 09509affd7922..e3c58e22388bc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -2831,21 +2831,34 @@ public class NotificationStackScrollLayout extends ViewGroup mAnimateNextBackgroundTop = false; mAnimateNextBackgroundBottom = false; } - if (firstChanged && mFirstVisibleBackgroundChild != null) { - mFirstVisibleBackgroundChild.setTopRoundness(0.0f); + if (firstChanged && mFirstVisibleBackgroundChild != null + && !mFirstVisibleBackgroundChild.isRemoved()) { + mFirstVisibleBackgroundChild.setTopRoundness(0.0f, + mFirstVisibleBackgroundChild.isShown()); } - if (lastChanged && mLastVisibleBackgroundChild != null) { - mLastVisibleBackgroundChild.setBottomRoundNess(0.0f); + if (lastChanged && mLastVisibleBackgroundChild != null + && !mLastVisibleBackgroundChild.isRemoved()) { + mLastVisibleBackgroundChild.setBottomRoundNess(0.0f, + mLastVisibleBackgroundChild.isShown()); } mFirstVisibleBackgroundChild = firstChild; mLastVisibleBackgroundChild = lastChild; + applyRoundedNess(); + mAmbientState.setLastVisibleBackgroundChild(lastChild); + } + + private void applyRoundedNess() { if (mFirstVisibleBackgroundChild != null) { - mFirstVisibleBackgroundChild.setTopRoundness(1.0f); + mFirstVisibleBackgroundChild.setTopRoundness( + mStatusBarState == StatusBarState.KEYGUARD ? 1.0f : 0.0f, + mFirstVisibleBackgroundChild.isShown() + && !mChildrenToAddAnimated.contains(mFirstVisibleBackgroundChild)); } if (mLastVisibleBackgroundChild != null) { - mLastVisibleBackgroundChild.setBottomRoundNess(1.0f); + mLastVisibleBackgroundChild.setBottomRoundNess(1.0f, + mLastVisibleBackgroundChild.isShown() + && !mChildrenToAddAnimated.contains(mLastVisibleBackgroundChild)); } - mAmbientState.setLastVisibleBackgroundChild(lastChild); } private void onViewAddedInternal(View child) { @@ -4300,6 +4313,7 @@ public class NotificationStackScrollLayout extends ViewGroup public void setStatusBarState(int statusBarState) { mStatusBarState = statusBarState; mAmbientState.setStatusBarState(statusBarState); + applyRoundedNess(); } public void setExpandingVelocity(float expandingVelocity) {