diff options
| author | 2016-11-01 19:11:41 -0700 | |
|---|---|---|
| committer | 2016-11-21 14:42:54 -0800 | |
| commit | d127d7923191c5023db423952d639f6ec8aa86cc (patch) | |
| tree | e716bea17782dbd5db5eb4f5ae42d115fe7868e2 | |
| parent | 25b5291e12c5de8be6137ff92afbd64ed54e7e8f (diff) | |
Modified heads up experience
When dragging down, the shelf is now hidden behind the notification
until it was fully revealed once.
Test: Add heads-up, drag down on it.
Bug: 32437839
Change-Id: I85133855428777a606a3039e26acf53e6e63a3bb
6 files changed, 96 insertions, 29 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java index 3c00c4e3eae9..a19978a9b6d6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java @@ -192,6 +192,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { private boolean mRefocusOnDismiss; private float mIconTransformationAmount; private boolean mIconsVisible = true; + private boolean mAboveShelf; public boolean isGroupExpansionChanging() { if (isChildInGroup()) { @@ -342,6 +343,9 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { if (intrinsicBefore != getIntrinsicHeight()) { notifyHeightChanged(false /* needsAnimation */); } + if (isHeadsUp) { + setAboveShelf(true); + } } public void setGroupManager(NotificationGroupManager groupManager) { @@ -529,12 +533,17 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { return mIsPinned; } + @Override + public int getPinnedHeadsUpHeight() { + return getPinnedHeadsUpHeight(true /* atLeastMinHeight */); + } + /** * @param atLeastMinHeight should the value returned be at least the minimum height. * Used to avoid cyclic calls * @return the height of the heads up notification when pinned */ - public int getPinnedHeadsUpHeight(boolean atLeastMinHeight) { + private int getPinnedHeadsUpHeight(boolean atLeastMinHeight) { if (mIsSummaryWithChildren) { return mChildrenContainer.getIntrinsicHeight(); } @@ -1778,6 +1787,15 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { return new NotificationViewState(stackScrollState); } + @Override + public boolean isAboveShelf() { + return mIsPinned || mHeadsupDisappearRunning || (mIsHeadsUp && mAboveShelf); + } + + public void setAboveShelf(boolean aboveShelf) { + mAboveShelf = aboveShelf; + } + public class NotificationViewState extends ExpandableViewState { private final StackScrollState mOverallState; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java index a75b8c51cd2e..0db0896d0754 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java @@ -289,6 +289,11 @@ public abstract class ExpandableView extends FrameLayout { public void setBelowShelf(boolean below) { } + public int getPinnedHeadsUpHeight() { + return getIntrinsicHeight(); + } + + /** * Sets the translation of the view. */ @@ -500,6 +505,10 @@ public abstract class ExpandableView extends FrameLayout { return mTransformingInShelf; } + public boolean isAboveShelf() { + return false; + } + /** * 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 da25852c47eb..9a1e0649c805 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java @@ -143,8 +143,7 @@ public class NotificationShelf extends ActivatableNotificationView { mShelfState.copyFrom(lastViewState); mShelfState.height = getIntrinsicHeight(); mShelfState.yTranslation = Math.min(viewEnd, maxShelfEnd) - mShelfState.height; - mShelfState.zTranslation = Math.max(mShelfState.zTranslation, - ambientState.getBaseZHeight()); + mShelfState.zTranslation = ambientState.getBaseZHeight(); float openedAmount = (mShelfState.yTranslation - getFullyClosedTranslation()) / (getIntrinsicHeight() * 2); openedAmount = Math.min(1.0f, openedAmount); @@ -192,7 +191,8 @@ public class NotificationShelf extends ActivatableNotificationView { IconState iconState = iconStates.get(icon); float notificationClipEnd; float shelfStart = getTranslationY(); - if (notGoneNotifications == shelfIndex - 1) { + boolean aboveShelf = row.getTranslationZ() > mAmbientState.getBaseZHeight(); + if (notGoneNotifications == shelfIndex - 1 || aboveShelf) { notificationClipEnd = shelfStart + getIntrinsicHeight(); } else { notificationClipEnd = shelfStart - mPaddingBetweenElements; @@ -205,11 +205,14 @@ public class NotificationShelf extends ActivatableNotificationView { } } updateNotificationClipHeight(row, notificationClipEnd); - updateIconAppearance(shelfStart, row, iconState, icon); + updateIconAppearance(row, iconState, icon); numIconsInShelf += iconState.iconAppearAmount; if (row.getTranslationY() >= getTranslationY() && mNotGoneIndex == -1) { mNotGoneIndex = notGoneNotifications; } + if (notGoneNotifications != 0 || !aboveShelf) { + row.setAboveShelf(false); + } notGoneNotifications++; } while (notificationIndex < mHostLayout.getChildCount()) { @@ -227,31 +230,33 @@ public class NotificationShelf extends ActivatableNotificationView { } mNotificationIconContainer.calculateIconTranslations(); mNotificationIconContainer.applyIconStates(); - setVisibility(numIconsInShelf == 0.0f ? INVISIBLE : VISIBLE); + setVisibility(numIconsInShelf == 0.0f || !mAmbientState.isShadeExpanded() ? INVISIBLE + : VISIBLE); setHideBackground(numIconsInShelf < 1.0f); } private void updateNotificationClipHeight(ExpandableNotificationRow row, float notificationClipEnd) { float viewEnd = row.getTranslationY() + row.getActualHeight(); - if (viewEnd > notificationClipEnd && !row.isPinned() && !row.isHeadsUpAnimatingAway()) { - // TODO: handle heads up clipping correctly when closing. + if (viewEnd > notificationClipEnd + && (mAmbientState.isShadeExpanded() + || (!row.isPinned() && !row.isHeadsUpAnimatingAway()))) { row.setClipBottomAmount((int) (viewEnd - notificationClipEnd)); } else { row.setClipBottomAmount(0); } } - private void updateIconAppearance(float shelfTransformationStart, ExpandableNotificationRow row, + private void updateIconAppearance(ExpandableNotificationRow row, IconState iconState, StatusBarIconView icon) { // Let calculate how much the view is in the shelf float viewStart = row.getTranslationY(); int transformHeight = row.getActualHeight() + mPaddingBetweenElements; float viewEnd = viewStart + transformHeight; - if (viewEnd >= shelfTransformationStart && !row.isPinned() - && !row.isHeadsUpAnimatingAway()) { - if (viewStart < shelfTransformationStart) { - float linearAmount = (shelfTransformationStart - viewStart) / transformHeight; + if (viewEnd >= getTranslationY() && (mAmbientState.isShadeExpanded() + || (!row.isPinned() && !row.isHeadsUpAnimatingAway()))) { + if (viewStart < getTranslationY()) { + float linearAmount = (getTranslationY() - viewStart) / transformHeight; float interpolatedAmount = Interpolators.ACCELERATE_DECELERATE.getInterpolation( linearAmount); float interpolationStart = mMaxLayoutHeight - getIntrinsicHeight() * 2; @@ -289,8 +294,9 @@ public class NotificationShelf extends ActivatableNotificationView { float transitionDistance = getIntrinsicHeight() * 1.5f; float transformationStartPosition = getTranslationY() - transitionDistance; float transitionAmount = 0.0f; - if (viewStart < transformationStartPosition || row.isPinned() - || row.isHeadsUpAnimatingAway()) { + if (viewStart < transformationStartPosition + || (!mAmbientState.isShadeExpanded() + && (row.isPinned() || row.isHeadsUpAnimatingAway()))) { // We simply place it on the icon of the notification iconState.yTranslation = notificationIconPosition - shelfIconPosition; } else { @@ -299,6 +305,9 @@ public class NotificationShelf extends ActivatableNotificationView { float startPosition = transformationStartPosition + iconTopPadding; iconState.yTranslation = NotificationUtils.interpolate( startPosition - shelfIconPosition, 0, transitionAmount); + // If we are merging into the shelf, lets make sure the shelf is at least on our height, + // otherwise the icons won't be visible. + setTranslationZ(Math.max(getTranslationZ(), row.getTranslationZ())); } float shelfIconSize = icon.getHeight() * icon.getIconScale(); if (!row.isShowingIcon()) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java index f6c0942d7ed0..c21c493f7636 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java @@ -103,6 +103,7 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL private boolean mWaitingOnCollapseWhenGoingAway; private boolean mIsObserving; private boolean mRemoteInputActive; + private float mExpandedHeight; public HeadsUpManager(final Context context, View statusBarWindowView, NotificationGroupManager groupManager) { @@ -513,7 +514,7 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL row = groupSummary; } } - return row.getPinnedHeadsUpHeight(true /* atLeastMinHeight */); + return row.getPinnedHeadsUpHeight(); } /** 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 a795b2a5bbb1..c9f819d0d44e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -760,6 +760,13 @@ public class NotificationStackScrollLayout extends ViewGroup * Measured in absolute height. */ private float getAppearStartPosition() { + if (mTrackingHeadsUp && mFirstVisibleBackgroundChild != null) { + if (mFirstVisibleBackgroundChild.isAboveShelf()) { + // If we ever expanded beyond the first notification, it's allowed to merge into + // the shelf + return mFirstVisibleBackgroundChild.getPinnedHeadsUpHeight(); + } + } return getMinExpansionHeight(); } @@ -4002,10 +4009,7 @@ public class NotificationStackScrollLayout extends ViewGroup } public int getMinExpansionHeight() { - return mTrackingHeadsUp - ? mHeadsUpManager.getTopHeadsUpPinnedHeight() - : mShelf.getIntrinsicHeight() - - (mShelf.getIntrinsicHeight() - mStatusBarHeight) / 2; + return mShelf.getIntrinsicHeight() - (mShelf.getIntrinsicHeight() - mStatusBarHeight) / 2; } public void setInHeadsUpPinnedMode(boolean inHeadsUpPinnedMode) { 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 651ac70a4748..764479fb03c0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java @@ -346,10 +346,10 @@ public class StackScrollAlgorithm { int childHeight = getMaxAllowedChildHeight(child); int collapsedHeight = child.getCollapsedHeight(); childViewState.yTranslation = currentYPosition; + boolean belowShelf = i >= ambientState.getShelfIndex(); if (i == 0) { - updateFirstChildHeight(child, childViewState, childHeight, ambientState); + updateFirstChildHeight(child, childViewState, childHeight, ambientState, belowShelf); } - boolean belowShelf = i >= ambientState.getShelfIndex(); // The y position after this element float nextYPosition = currentYPosition + childHeight + @@ -422,7 +422,10 @@ public class StackScrollAlgorithm { if (mIsExpanded) { // Ensure that the heads up is always visible even when scrolled off clampHunToTop(ambientState, row, childState); - clampHunToMaxTranslation(ambientState, row, childState); + if (i == 0) { + // the first hun can't get off screen. + clampHunToMaxTranslation(ambientState, row, childState); + } } if (row.isPinned()) { childState.yTranslation = Math.max(childState.yTranslation, 0); @@ -570,20 +573,27 @@ public class StackScrollAlgorithm { /** * Update the height of the first child i.e clamp it to the bottom stack - * - * @param child the child to update + * @param child the child to update * @param childViewState the viewstate of the child * @param childHeight the height of the child * @param ambientState The ambient state of the algorithm + * @param belowShelf */ protected void updateFirstChildHeight(ExpandableView child, ExpandableViewState childViewState, - int childHeight, AmbientState ambientState) { + int childHeight, AmbientState ambientState, boolean belowShelf) { + int bottomStart; + if (belowShelf) { // The starting position of the bottom stack peek - int bottomPeekStart = ambientState.getInnerHeight() - mBottomStackPeekSize - - mBottomStackSlowDownLength + ambientState.getScrollY(); + bottomStart = ambientState.getInnerHeight() - mBottomStackPeekSize - + mBottomStackSlowDownLength; + } else { + bottomStart = ambientState.getInnerHeight() + - 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(bottomPeekStart, (float) childHeight), + childViewState.height = (int) Math.max(Math.min(bottomStart, (float) childHeight), child.getCollapsedHeight()); } @@ -643,6 +653,22 @@ public class StackScrollAlgorithm { } childViewState.zTranslation = baseZ + childrenOnTop * zDistanceBetweenElements; + } else if (i == 0 && child.isAboveShelf()) { + // 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 + int shelfHeight = ambientState.getShelf().getIntrinsicHeight(); + float shelfStart = ambientState.getInnerHeight() + - shelfHeight + ambientState.getTopPadding() + + ambientState.getStackTranslation(); + float notificationEnd = childViewState.yTranslation + child.getPinnedHeadsUpHeight() + + mPaddingBetweenElements; + if (shelfStart > notificationEnd) { + childViewState.zTranslation = baseZ; + } else { + float factor = (notificationEnd - shelfStart) / shelfHeight; + factor = Math.min(factor, 1.0f); + childViewState.zTranslation = baseZ + factor * zDistanceBetweenElements; + } } else { childViewState.zTranslation = baseZ; } |