From b3dadccbc5c7040260a51a3e17efcb74aeec6a11 Mon Sep 17 00:00:00 2001 From: Selim Cinek Date: Mon, 21 Nov 2016 17:21:13 -0800 Subject: [PATCH] Improved the clipping of notification groups Groups now correctly respect the clipBottomAmount and animations work much better when swiping things away. Also removed the group measuring logic when expanding, Since we're now not shrinking the first notification anymore! This also fixed a bug where a child could be invisible Test: Add group, swipe children away Bug: 32437839 Bug: 33203156 Change-Id: I255aa9695086e64eb10c7dccdc6122d8a8572bb5 --- .../statusbar/ExpandableNotificationRow.java | 6 +-- .../statusbar/ExpandableOutlineView.java | 8 ++- .../systemui/statusbar/ExpandableView.java | 11 ++-- .../systemui/statusbar/NotificationShelf.java | 1 - .../phone/NotificationIconContainer.java | 2 +- .../statusbar/stack/ExpandableViewState.java | 6 --- .../stack/NotificationChildrenContainer.java | 51 ++++++++++++++----- .../stack/NotificationStackScrollLayout.java | 30 ++--------- .../statusbar/stack/StackScrollAlgorithm.java | 26 ---------- 9 files changed, 57 insertions(+), 84 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java index a1384dcbe66d8..661cc3ca2b4ae 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java @@ -1685,6 +1685,9 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { if (mGuts != null) { mGuts.setClipBottomAmount(clipBottomAmount); } + if (mChildrenContainer != null) { + mChildrenContainer.setClipBottomAmount(clipBottomAmount); + } } public boolean isMaxExpandHeightInitialized() { @@ -1863,9 +1866,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { super.applyToView(view); if (view instanceof ExpandableNotificationRow) { ExpandableNotificationRow row = (ExpandableNotificationRow) view; - if (this.isBottomClipped) { - row.setClipToActualHeight(true); - } row.applyChildrenState(mOverallState); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java index 4b95f073c843e..91abc8779274c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java @@ -41,7 +41,7 @@ public abstract class ExpandableOutlineView extends ExpandableView { outline.setRect(translation, mClipTopAmount, getWidth() + translation, - Math.max(getActualHeight(), mClipTopAmount)); + Math.max(getActualHeight() - mClipBottomAmount, mClipTopAmount)); } else { outline.setRect(mOutlineRect); } @@ -66,6 +66,12 @@ public abstract class ExpandableOutlineView extends ExpandableView { invalidateOutline(); } + @Override + public void setClipBottomAmount(int clipBottomAmount) { + super.setClipBottomAmount(clipBottomAmount); + invalidateOutline(); + } + protected void setOutlineAlpha(float alpha) { if (alpha != mOutlineAlpha) { mOutlineAlpha = alpha; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java index 0f5981bc84891..37a900e52e86b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java @@ -38,7 +38,7 @@ public abstract class ExpandableView extends FrameLayout { protected OnHeightChangedListener mOnHeightChangedListener; private int mActualHeight; protected int mClipTopAmount; - private float mClipBottomAmount; + protected int mClipBottomAmount; private boolean mDark; private ArrayList mMatchParentViews = new ArrayList(); private static Rect mClipRect = new Rect(); @@ -241,7 +241,7 @@ public abstract class ExpandableView extends FrameLayout { return mClipTopAmount; } - public float getClipBottomAmount() { + public int getClipBottomAmount() { return mClipBottomAmount; } @@ -354,11 +354,8 @@ public abstract class ExpandableView extends FrameLayout { private void updateClipping() { if (mClipToActualHeight) { int top = getClipTopAmount(); - if (top >= getActualHeight()) { - top = getActualHeight() - 1; - } - mClipRect.set(0, top, getWidth(), (int) (getActualHeight() + getExtraBottomPadding() - - mClipBottomAmount)); + mClipRect.set(0, top, getWidth(), Math.max(getActualHeight() + getExtraBottomPadding() + - mClipBottomAmount, top)); setClipBounds(mClipRect); } else { setClipBounds(null); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java index add47641c4b6a..680562aa670b0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java @@ -156,7 +156,6 @@ public class NotificationShelf extends ActivatableNotificationView { mShelfState.alpha = 1.0f; mShelfState.belowSpeedBump = mAmbientState.getSpeedBumpIndex() == 0; mShelfState.shadowAlpha = 1.0f; - mShelfState.isBottomClipped = false; mShelfState.hideSensitive = false; mShelfState.xTranslation = getTranslationX(); if (mNotGoneIndex != -1) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java index 28958908f81bc..03697b86e31e0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java @@ -48,7 +48,7 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout { return mAnimationFilter; } }.setDuration(200); - + private static final AnimationProperties ADD_ICON_PROPERTIES = new AnimationProperties() { private AnimationFilter mAnimationFilter = new AnimationFilter().animateAlpha(); 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 58e6838c815b8..7854c98ce47e7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/ExpandableViewState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ExpandableViewState.java @@ -106,11 +106,6 @@ public class ExpandableViewState extends ViewState { */ public int location; - /** - * Whether a child in a group is being clipped at the bottom. - */ - public boolean isBottomClipped; - @Override public void copyFrom(ViewState viewState) { super.copyFrom(viewState); @@ -125,7 +120,6 @@ public class ExpandableViewState extends ViewState { clipTopAmount = svs.clipTopAmount; notGoneIndex = svs.notGoneIndex; location = svs.location; - isBottomClipped = svs.isBottomClipped; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java index 26e134273f197..b8f8cb2b5bc91 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java @@ -76,6 +76,7 @@ public class NotificationChildrenContainer extends ViewGroup { private NotificationViewWrapper mNotificationHeaderWrapper; private NotificationHeaderUtil mHeaderUtil; private ViewState mHeaderViewState; + private int mClipBottomAmount; public NotificationChildrenContainer(Context context) { this(context, null); @@ -433,7 +434,6 @@ public class NotificationChildrenContainer extends ViewGroup { boolean childrenExpanded = !mNotificationParent.isGroupExpansionChanging() && mChildrenExpanded; - int parentHeight = parentState.height; for (int i = 0; i < childCount; i++) { ExpandableNotificationRow child = mChildren.get(i); if (!firstChild) { @@ -457,20 +457,9 @@ public class NotificationChildrenContainer extends ViewGroup { ExpandableViewState childState = resultState.getViewStateForView(child); int intrinsicHeight = child.getIntrinsicHeight(); - if (childrenExpanded) { - // When a group is expanded and moving into bottom stack, the bottom visible child - // adjusts its height to move into it. Children after it are hidden. - if (updateChildStateForExpandedGroup(child, parentHeight, childState, yPosition)) { - // Clipping might be deactivated if the view is transforming, however, clipping - // the child into the bottom stack should take precedent over this. - childState.isBottomClipped = true; - } - } else { - childState.hidden = false; - childState.height = intrinsicHeight; - childState.isBottomClipped = false; - } + childState.height = intrinsicHeight; childState.yTranslation = yPosition; + 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 = childrenExpanded @@ -601,6 +590,34 @@ public class NotificationChildrenContainer extends ViewGroup { if (mHeaderViewState != null) { mHeaderViewState.applyToView(mNotificationHeader); } + updateChildrenClipping(); + } + + private void updateChildrenClipping() { + int childCount = mChildren.size(); + int layoutEnd = mNotificationParent.getActualHeight() - mClipBottomAmount; + for (int i = 0; i < childCount; i++) { + ExpandableNotificationRow child = mChildren.get(i); + if (child.getVisibility() == GONE) { + continue; + } + float childTop = child.getTranslationY(); + float childBottom = childTop + child.getActualHeight(); + boolean visible = true; + int clipBottomAmount = 0; + if (childTop > layoutEnd) { + visible = false; + } else if (childBottom > layoutEnd) { + clipBottomAmount = (int) (childBottom - layoutEnd); + } + + boolean isVisible = child.getVisibility() == VISIBLE; + if (visible != isVisible) { + child.setVisibility(visible ? VISIBLE : INVISIBLE); + } + + child.setClipBottomAmount(clipBottomAmount); + } } /** @@ -653,6 +670,7 @@ public class NotificationChildrenContainer extends ViewGroup { if (mNotificationHeader != null) { mHeaderViewState.applyToView(mNotificationHeader); } + updateChildrenClipping(); } public ExpandableNotificationRow getViewAtPosition(float y) { @@ -889,4 +907,9 @@ public class NotificationChildrenContainer extends ViewGroup { } } } + + public void setClipBottomAmount(int clipBottomAmount) { + mClipBottomAmount = clipBottomAmount; + updateChildrenClipping(); + } } 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 522e4a93b40e8..e8e3adb31bf7d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -766,12 +766,14 @@ public class NotificationStackScrollLayout extends ViewGroup */ private float getAppearEndPosition() { int appearPosition; + int minNotificationsForShelf = 1; if (mTrackingHeadsUp || mHeadsUpManager.hasPinnedHeadsUp()) { appearPosition = mHeadsUpManager.getTopHeadsUpPinnedHeight(); + minNotificationsForShelf = 2; } else { - appearPosition = getFirstItemMinHeight(); + appearPosition = 0; } - if (getNotGoneChildCount() > 1) { + if (getNotGoneChildCount() >= minNotificationsForShelf) { appearPosition += mShelf.getIntrinsicHeight(); } return appearPosition + (onKeyguard() ? mTopPadding : mIntrinsicPadding); @@ -1092,29 +1094,7 @@ public class NotificationStackScrollLayout extends ViewGroup @Override public int getMaxExpandHeight(ExpandableView view) { - int maxContentHeight = view.getMaxContentHeight(); - if (view.isSummaryWithChildren() && view.getParent() == this) { - // Faking a measure with the group expanded to simulate how the group would look if - // it was. Doing a calculation here would be highly non-trivial because of the - // algorithm - mGroupExpandedForMeasure = true; - ExpandableNotificationRow row = (ExpandableNotificationRow) view; - mGroupManager.toggleGroupExpansion(row.getStatusBarNotification()); - row.setForceUnlocked(true); - mAmbientState.setLayoutHeight(mMaxLayoutHeight); - mStackScrollAlgorithm.getStackScrollState(mAmbientState, mCurrentStackScrollState); - mAmbientState.setLayoutHeight(getLayoutHeight()); - mGroupManager.toggleGroupExpansion( - row.getStatusBarNotification()); - mGroupExpandedForMeasure = false; - row.setForceUnlocked(false); - ExpandableViewState viewState = mCurrentStackScrollState.getViewStateForView(view); - if (viewState != null) { - // The view could have been removed - return Math.min(viewState.height, maxContentHeight); - } - } - return maxContentHeight; + return view.getMaxContentHeight(); } public void setScrollingEnabled(boolean enable) { 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 1dc346d7c61b0..17e73d2141358 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java @@ -323,9 +323,6 @@ public class StackScrollAlgorithm { int childHeight = getMaxAllowedChildHeight(child); childViewState.yTranslation = currentYPosition; boolean isDismissView = child instanceof DismissView; - if (i == 0) { - updateFirstChildHeight(child, childViewState, childHeight, algorithmState, ambientState); - } childViewState.location = ExpandableViewState.LOCATION_MAIN_AREA; if (isDismissView) { @@ -449,29 +446,6 @@ public class StackScrollAlgorithm { return child == null? mCollapsedSize : child.getHeight(); } - /** - * Update the height of the first child i.e clamp it to the bottom stack - * @param child the child to update - * @param childViewState the viewstate of the child - * @param childHeight the height of the child - * @param algorithmState the algorithm state - * @param ambientState The ambient state of the algorithm - */ - protected void updateFirstChildHeight(ExpandableView child, ExpandableViewState childViewState, - int childHeight, StackScrollAlgorithmState algorithmState, - AmbientState ambientState) { - - int bottomStart= ambientState.getInnerHeight(); - if (algorithmState.visibleChildren.size() > 1) { - bottomStart -= ambientState.getShelf().getIntrinsicHeight() - - mPaddingBetweenElements; - } - bottomStart += ambientState.getScrollY(); - // Collapse and expand the first child while the shade is being expanded - childViewState.height = (int) Math.max(Math.min(bottomStart, (float) childHeight), - child.getCollapsedHeight()); - } - /** * Calculate the Z positions for all children based on the number of items in both stacks and * save it in the resultState