diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java index 80f3131456845..a75b8c51cd2ec 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java @@ -47,6 +47,8 @@ public abstract class ExpandableView extends FrameLayout { private boolean mClipToActualHeight = true; private boolean mChangingPosition = false; private ViewGroup mTransientContainer; + private boolean mInShelf; + private boolean mTransformingInShelf; public ExpandableView(Context context, AttributeSet attrs) { super(context, attrs); @@ -475,6 +477,29 @@ public abstract class ExpandableView extends FrameLayout { return false; } + /** + * @param inShelf whether the view is currently fully in the notification shelf. + */ + public void setInShelf(boolean inShelf) { + mInShelf = inShelf; + } + + public boolean isInShelf() { + return mInShelf; + } + + /** + * @param transformingInShelf whether the view is currently transforming into the shelf in an + * animated way + */ + public void setTransformingInShelf(boolean transformingInShelf) { + mTransformingInShelf = transformingInShelf; + } + + public boolean isTransformingIntoShelf() { + return mTransformingInShelf; + } + /** * A listener notifying when {@link #getActualHeight} changes. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java index 3a49de224ff76..9fc9b8f878a46 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java @@ -60,6 +60,8 @@ public class NotificationShelf extends ActivatableNotificationView { private NotificationStackScrollLayout mHostLayout; private int mMaxLayoutHeight; private int mPaddingBetweenElements; + private int mNotGoneIndex; + private boolean mHasItemsInStableShelf; public NotificationShelf(Context context, AttributeSet attrs) { super(context, attrs); @@ -154,9 +156,14 @@ public class NotificationShelf extends ActivatableNotificationView { mShelfState.shadowAlpha = 1.0f; mShelfState.isBottomClipped = false; mShelfState.hideSensitive = false; + if (mNotGoneIndex != -1) { + mShelfState.notGoneIndex = Math.min(mShelfState.notGoneIndex, mNotGoneIndex); + } + mShelfState.hasItemsInStableShelf = lastViewState.inShelf; } else { mShelfState.hidden = true; mShelfState.location = ExpandableViewState.LOCATION_GONE; + mShelfState.hasItemsInStableShelf = false; } } @@ -169,6 +176,7 @@ public class NotificationShelf extends ActivatableNotificationView { mNotificationIconContainer.resetViewStates(); float numIconsInShelf = 0.0f; int shelfIndex = mAmbientState.getShelfIndex(); + mNotGoneIndex = -1; // find the first view that doesn't overlap with the shelf for (int i = shelfIndex - 1; i >= 0; i--) { ExpandableView child = (ExpandableView) mHostLayout.getChildAt(i); @@ -198,6 +206,9 @@ public class NotificationShelf extends ActivatableNotificationView { updateNotificationClipHeight(row, notificationClipEnd); updateIconAppearance(shelfStart, row, iconState, icon); numIconsInShelf += iconState.iconAppearAmount; + if (row.getTranslationY() >= getTranslationY()) { + mNotGoneIndex = i; + } } for (int i = mHostLayout.getChildCount() - 1; i >= shelfIndex; i--) { // We need to reset the clipping in case a notification switches from high to low @@ -301,6 +312,13 @@ public class NotificationShelf extends ActivatableNotificationView { iconState.hidden = transitionAmount == 0.0f; row.setIconTransformationAmount(transitionAmount); icon.setVisibility(transitionAmount == 0.0f ? INVISIBLE : VISIBLE); + if (row.isInShelf() && !row.isTransformingIntoShelf()) { + iconState.iconAppearAmount = 1.0f; + iconState.alpha = 1.0f; + iconState.scaleX = shelfIconSize / icon.getHeight(); + iconState.scaleY = iconState.scaleX; + iconState.hidden = false; + } } private float getFullyClosedTranslation() { @@ -335,6 +353,10 @@ public class NotificationShelf extends ActivatableNotificationView { updateOutline(); } + public boolean hidesBackground() { + return mHideBackground; + } + @Override protected boolean needsOutline() { return !mHideBackground && super.needsOutline(); @@ -353,14 +375,35 @@ public class NotificationShelf extends ActivatableNotificationView { mMaxLayoutHeight = maxLayoutHeight; } + /** + * @return the index of the notification at which the shelf visually resides + */ + public int getNotGoneIndex() { + return mNotGoneIndex; + } + + private void setHasItemsInStableShelf(boolean hasItemsInStableShelf) { + mHasItemsInStableShelf = hasItemsInStableShelf; + } + + /** + * @return whether the shelf has any icons in it when a potential animation has finished, i.e + * if the current state would be applied right now + */ + public boolean hasItemsInStableShelf() { + return mHasItemsInStableShelf; + } + private class ShelfState extends ExpandableViewState { private float iconContainerTranslation; + private boolean hasItemsInStableShelf; @Override public void applyToView(View view) { super.applyToView(view); updateAppearance(); setIconContainerTranslation(iconContainerTranslation); + setHasItemsInStableShelf(hasItemsInStableShelf); } @Override @@ -368,6 +411,7 @@ public class NotificationShelf extends ActivatableNotificationView { super.animateTo(child, properties); updateAppearance(); setIconContainerTranslation(iconContainerTranslation); + setHasItemsInStableShelf(hasItemsInStableShelf); } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/ExpandableViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ExpandableViewState.java index 0472db092e40b..7c719d8f3fd94 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/ExpandableViewState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ExpandableViewState.java @@ -86,6 +86,7 @@ public class ExpandableViewState extends ViewState { public boolean hideSensitive; public boolean belowShelf; public float shadowAlpha; + public boolean inShelf; /** * How much the child overlaps with the previous child on top. This is used to @@ -171,6 +172,9 @@ public class ExpandableViewState extends ViewState { if (oldClipTopAmount != this.clipTopAmount) { expandableView.setClipTopAmount(this.clipTopAmount); } + + expandableView.setTransformingInShelf(false); + expandableView.setInShelf(inShelf); } } @@ -220,6 +224,11 @@ public class ExpandableViewState extends ViewState { if (properties.wasAdded(child)) { expandableView.performAddAnimation(properties.delay, properties.duration); } + + if (!expandableView.isInShelf() && this.inShelf) { + expandableView.setTransformingInShelf(true); + } + expandableView.setInShelf(this.inShelf); } private void startHeightAnimation(final ExpandableView child, AnimationProperties properties) { 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 1a6e492723c90..0ec27ab686f8c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -2127,10 +2127,17 @@ public class NotificationStackScrollLayout extends ViewGroup top = (int) firstView.getTranslationY(); } } - ActivatableNotificationView lastView = mLastVisibleBackgroundChild; + ActivatableNotificationView lastView = mShelf.hasItemsInStableShelf() + ? mShelf + : mLastVisibleBackgroundChild; int bottom = 0; if (lastView != null) { - int finalTranslationY = (int) ViewState.getFinalTranslationY(lastView); + int finalTranslationY; + if (lastView == mShelf) { + finalTranslationY = (int) mShelf.getTranslationY(); + } else { + finalTranslationY = (int) ViewState.getFinalTranslationY(lastView); + } int finalHeight = ExpandableViewState.getFinalActualHeight(lastView); int finalBottom = finalTranslationY + finalHeight; finalBottom = Math.min(finalBottom, getHeight()); @@ -3979,6 +3986,7 @@ public class NotificationStackScrollLayout extends ViewGroup } addView(mShelf, index); mAmbientState.setShelf(shelf); + mStateAnimator.setShelf(shelf); shelf.bind(mAmbientState, this); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java index 409d41556eadd..651ac70a47486 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java @@ -501,6 +501,7 @@ public class StackScrollAlgorithm { childViewState.yTranslation = Math.min(childViewState.yTranslation, shelfStart); if (childViewState.yTranslation >= shelfStart) { childViewState.hidden = true; + childViewState.inShelf = true; } if (!ambientState.isShadeExpanded()) { childViewState.height = (int) (mStatusBarHeight - childViewState.yTranslation); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java index 7cf9ec1b5a956..e3c746bf0d329 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java @@ -83,6 +83,7 @@ public class StackScrollState { viewState.hidden = false; viewState.scaleX = view.getScaleX(); viewState.scaleY = view.getScaleY(); + viewState.inShelf = false; } public ExpandableViewState getViewStateForView(View requestedView) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java index 5cf0a27fcb906..342d307954549 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java @@ -28,6 +28,7 @@ import com.android.systemui.Interpolators; import com.android.systemui.R; import com.android.systemui.statusbar.ExpandableNotificationRow; import com.android.systemui.statusbar.ExpandableView; +import com.android.systemui.statusbar.NotificationShelf; import java.util.ArrayList; import java.util.HashSet; @@ -75,6 +76,7 @@ public class StackStateAnimator { private int mHeadsUpAppearHeightBottom; private boolean mShadeExpanded; private ArrayList mChildrenToClearFromOverlay = new ArrayList<>(); + private NotificationShelf mShelf; public StackStateAnimator(NotificationStackScrollLayout hostLayout) { mHostLayout = hostLayout; @@ -287,9 +289,18 @@ public class StackStateAnimator { } private long calculateDelayGoToFullShade(ExpandableViewState viewState) { + int shelfIndex = mShelf.getNotGoneIndex(); float index = viewState.notGoneIndex; + long result = 0; + if (index > shelfIndex) { + float diff = index - shelfIndex; + diff = (float) Math.pow(diff, 0.7f); + result += (long) (diff * ANIMATION_DELAY_PER_ELEMENT_GO_TO_FULL_SHADE * 0.25); + index = shelfIndex; + } index = (float) Math.pow(index, 0.7f); - return (long) (index * ANIMATION_DELAY_PER_ELEMENT_GO_TO_FULL_SHADE); + result += (long) (index * ANIMATION_DELAY_PER_ELEMENT_GO_TO_FULL_SHADE); + return result; } /** @@ -501,4 +512,8 @@ public class StackStateAnimator { public void setShadeExpanded(boolean shadeExpanded) { mShadeExpanded = shadeExpanded; } + + public void setShelf(NotificationShelf shelf) { + mShelf = shelf; + } }