Adjusted the behavior when expanding the notification panel

The topmost notification is now not collapsed anymore but slides in
expanded from the top. Therefore it's layout doesn't need to animate
anymore. This also cleans up a lot of code in the algorithm which was
depending on this resizing which isn't needed anymore.
In order to have that transition working perfectly, the padding when
collapsing a card is now the same as the slowdown length.
Also improved the logic when notification contents are allowed to
animate and when not.
Also fixed a bug where the top notification was cut off when QS was
expanded.

Bug: 27402534
Bug: 18434284
Change-Id: I31afa199d38d94e74fd45500c2236ffdb51d989d
This commit is contained in:
Selim Cinek
2016-03-01 17:52:20 -08:00
parent 8351ff25a1
commit d1ad9ab312
5 changed files with 32 additions and 145 deletions

View File

@@ -326,9 +326,6 @@
<!-- The minimum amount of top overscroll to go to the quick settings. -->
<dimen name="min_top_overscroll_to_qs">36dp</dimen>
<!-- The padding to the second card when the notifications collapse. -->
<dimen name="notification_collapse_second_card_padding">8dp</dimen>
<!-- The height of the speed bump view. -->
<dimen name="speed_bump_height">16dp</dimen>

View File

@@ -92,7 +92,14 @@ public class NotificationContentView extends FrameLayout {
= new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
mAnimate = true;
// We need to post since we don't want the notification to animate on the very first
// frame
post(new Runnable() {
@Override
public void run() {
mAnimate = true;
}
});
getViewTreeObserver().removeOnPreDrawListener(this);
return true;
}

View File

@@ -1397,7 +1397,7 @@ public class NotificationPanelView extends PanelView implements
// In Shade, interpolate linearly such that QS is closed whenever panel height is
// minimum QS expansion + minStackHeight
float panelHeightQsCollapsed = mNotificationStackScroller.getIntrinsicPadding()
+ mNotificationStackScroller.getMinStackHeight();
+ mNotificationStackScroller.getLayoutMinHeight();
float panelHeightQsExpanded = calculatePanelHeightQsExpanded();
t = (expandedHeight - panelHeightQsCollapsed)
/ (panelHeightQsExpanded - panelHeightQsCollapsed);
@@ -1453,7 +1453,7 @@ public class NotificationPanelView extends PanelView implements
&& mShadeEmpty) {
notificationHeight = mNotificationStackScroller.getEmptyShadeViewHeight()
+ mNotificationStackScroller.getBottomStackPeekSize()
+ mNotificationStackScroller.getCollapseSecondCardPadding();
+ mNotificationStackScroller.getBottomStackSlowDownHeight();
}
int maxQsHeight = mQsMaxExpansionHeight;
@@ -1468,7 +1468,7 @@ public class NotificationPanelView extends PanelView implements
+ notificationHeight;
if (totalHeight > mNotificationStackScroller.getHeight()) {
float fullyCollapsedHeight = maxQsHeight
+ mNotificationStackScroller.getMinStackHeight();
+ mNotificationStackScroller.getLayoutMinHeight();
totalHeight = Math.max(fullyCollapsedHeight, mNotificationStackScroller.getHeight());
}
return (int) totalHeight;
@@ -1485,7 +1485,7 @@ public class NotificationPanelView extends PanelView implements
private float getFadeoutAlpha() {
float alpha = (getNotificationsTopY() + mNotificationStackScroller.getFirstItemMinHeight())
/ (mQsMinExpansionHeight + mNotificationStackScroller.getBottomStackPeekSize()
- mNotificationStackScroller.getCollapseSecondCardPadding());
- mNotificationStackScroller.getBottomStackSlowDownHeight());
alpha = Math.max(0, Math.min(alpha, 1));
alpha = (float) Math.pow(alpha, 0.75);
return alpha;

View File

@@ -418,12 +418,9 @@ public class NotificationStackScrollLayout extends ViewGroup
.getDimensionPixelSize(R.dimen.notification_divider_height));
mIncreasedPaddingBetweenElements = context.getResources()
.getDimensionPixelSize(R.dimen.notification_divider_height_increased);
mBottomStackSlowDownHeight = mStackScrollAlgorithm.getBottomStackSlowDownLength();
mMinTopOverScrollToEscape = getResources().getDimensionPixelSize(
R.dimen.min_top_overscroll_to_qs);
mCollapseSecondCardPadding = getResources().getDimensionPixelSize(
R.dimen.notification_collapse_second_card_padding);
}
private void notifyHeightChangeListener(ExpandableView view) {
@@ -508,14 +505,6 @@ public class NotificationStackScrollLayout extends ViewGroup
mAmbientState.setTopPadding(mTopPadding);
}
/**
* @return whether the height of the layout needs to be adapted, in order to ensure that the
* last child is not in the bottom stack.
*/
private boolean needsHeightAdaption() {
return getNotGoneChildCount() > 1;
}
/**
* Updates the children views according to the stack scroll algorithm. Call this whenever
* modifications to {@link #mOwnScrollY} are performed to reflect it in the view layout.
@@ -599,7 +588,7 @@ public class NotificationStackScrollLayout extends ViewGroup
mLastSetStackHeight = height;
setIsExpanded(height > 0.0f);
int newStackHeight = (int) height;
int minStackHeight = getMinStackHeight();
int minStackHeight = getLayoutMinHeight();
int stackHeight;
float paddingOffset;
boolean trackingHeadsUp = mTrackingHeadsUp || mHeadsUpManager.hasPinnedHeadsUp();
@@ -612,20 +601,7 @@ public class NotificationStackScrollLayout extends ViewGroup
stackHeight = newStackHeight;
} else {
int translationY;
if (!trackingHeadsUp) {
// We did not reach the position yet where we actually start growing,
// so we translate the stack upwards.
translationY = (newStackHeight - minStackHeight);
// A slight parallax effect is introduced in order for the stack to catch up with
// the top card.
float partiallyThere = (newStackHeight - mTopPadding - mTopPaddingOverflow)
/ minStackHeight;
partiallyThere = Math.max(0, partiallyThere);
translationY += (1 - partiallyThere) * (mBottomStackPeekSize +
mCollapseSecondCardPadding);
} else {
translationY = (int) (height - normalUnfoldPositionStart);
}
translationY = newStackHeight - normalUnfoldPositionStart;
paddingOffset = translationY - mTopPadding;
stackHeight = (int) (height - (translationY - mTopPadding));
}
@@ -668,8 +644,8 @@ public class NotificationStackScrollLayout extends ViewGroup
return mBottomStackPeekSize;
}
public int getCollapseSecondCardPadding() {
return mCollapseSecondCardPadding;
public int getBottomStackSlowDownHeight() {
return mBottomStackSlowDownHeight;
}
public void setLongPressListener(SwipeHelper.LongPressListener listener) {
@@ -1850,7 +1826,7 @@ public class NotificationStackScrollLayout extends ViewGroup
boolean ignoreIntrinsicPadding) {
float start = qsHeight;
float stackHeight = getHeight() - start;
int minStackHeight = getMinStackHeight();
int minStackHeight = getLayoutMinHeight();
if (stackHeight <= minStackHeight) {
float overflow = minStackHeight - stackHeight;
stackHeight = minStackHeight;
@@ -1864,11 +1840,16 @@ public class NotificationStackScrollLayout extends ViewGroup
setStackHeight(mLastSetStackHeight);
}
public int getMinStackHeight() {
public int getLayoutMinHeight() {
final ExpandableView firstChild = getFirstChildNotGone();
final int firstChildMinHeight = firstChild != null ? firstChild.getMinHeight()
int firstChildMinHeight = firstChild != null
? firstChild.getIntrinsicHeight()
: mCollapsedSize;
return firstChildMinHeight + mBottomStackPeekSize + mCollapseSecondCardPadding;
if (mOwnScrollY > 0) {
firstChildMinHeight = Math.max(firstChildMinHeight - mOwnScrollY, mCollapsedSize);
}
return Math.min(firstChildMinHeight + mBottomStackPeekSize + mBottomStackSlowDownHeight,
mMaxLayoutHeight - mTopPadding);
}
public float getTopPaddingOverflow() {
@@ -1880,7 +1861,7 @@ public class NotificationStackScrollLayout extends ViewGroup
final int firstChildMinHeight = firstChild != null ? (int) firstChild.getMinHeight()
: mCollapsedSize;
return mIntrinsicPadding + firstChildMinHeight + mBottomStackPeekSize
+ mCollapseSecondCardPadding;
+ mBottomStackSlowDownHeight;
}
private int clampPadding(int desiredPadding) {
@@ -1994,7 +1975,6 @@ public class NotificationStackScrollLayout extends ViewGroup
}
private void onViewRemovedInternal(View child) {
mStackScrollAlgorithm.notifyChildrenChanged(this);
if (mChangePositionInProgress) {
// This is only a position change, don't do anything special
return;
@@ -2175,7 +2155,6 @@ public class NotificationStackScrollLayout extends ViewGroup
private void onViewAddedInternal(View child) {
updateHideSensitiveForChild(child);
mStackScrollAlgorithm.notifyChildrenChanged(this);
((ExpandableView) child).setOnHeightChangedListener(this);
generateAddAnimation(child, false /* fromMoreCard */);
updateAnimationState(child);
@@ -2643,12 +2622,8 @@ public class NotificationStackScrollLayout extends ViewGroup
}
public int getEmptyBottomMargin() {
int emptyMargin = mMaxLayoutHeight - mContentHeight - mBottomStackPeekSize;
if (needsHeightAdaption()) {
emptyMargin -= mBottomStackSlowDownHeight;
} else {
emptyMargin -= mCollapseSecondCardPadding;
}
int emptyMargin = mMaxLayoutHeight - mContentHeight - mBottomStackPeekSize
- mBottomStackSlowDownHeight;
return Math.max(emptyMargin, 0);
}
@@ -2659,12 +2634,10 @@ public class NotificationStackScrollLayout extends ViewGroup
public void onExpansionStarted() {
mIsExpansionChanging = true;
mStackScrollAlgorithm.onExpansionStarted(mCurrentStackScrollState);
}
public void onExpansionStopped() {
mIsExpansionChanging = false;
mStackScrollAlgorithm.onExpansionStopped();
if (!mIsExpanded) {
mOwnScrollY = 0;
@@ -2732,7 +2705,6 @@ public class NotificationStackScrollLayout extends ViewGroup
if (mIsExpanded && mAnimationsEnabled) {
mRequestViewResizeAnimationOnLayout = true;
}
mStackScrollAlgorithm.onReset(view);
updateAnimationState(view);
updateChronometerForChild(view);
}
@@ -3163,15 +3135,7 @@ public class NotificationStackScrollLayout extends ViewGroup
}
public int getDismissViewHeight() {
int height = mDismissView.getHeight() + mPaddingBetweenElements;
// Hack: Accommodate for additional distance when we only have one notification and the
// dismiss all button.
if (getNotGoneChildCount() == 2 && getLastChildNotGone() == mDismissView
&& getFirstChildNotGone() instanceof ActivatableNotificationView) {
height += mCollapseSecondCardPadding;
}
return height;
return mDismissView.getHeight() + mPaddingBetweenElements;
}
public int getEmptyShadeViewHeight() {

View File

@@ -52,13 +52,8 @@ public class StackScrollAlgorithm {
private StackIndentationFunctor mBottomStackIndentationFunctor;
private StackScrollAlgorithmState mTempAlgorithmState = new StackScrollAlgorithmState();
private boolean mIsExpansionChanging;
private int mFirstChildMaxHeight;
private boolean mIsExpanded;
private ExpandableView mFirstChildWhileExpanding;
private boolean mExpandedOnStart;
private int mBottomStackSlowDownLength;
private int mCollapseSecondCardPadding;
public StackScrollAlgorithm(Context context) {
initView(context);
@@ -86,8 +81,6 @@ public class StackScrollAlgorithm {
mZBasicHeight = (MAX_ITEMS_IN_BOTTOM_STACK + 1) * mZDistanceBetweenElements;
mBottomStackSlowDownLength = context.getResources()
.getDimensionPixelSize(R.dimen.bottom_stack_slow_down_length);
mCollapseSecondCardPadding = context.getResources().getDimensionPixelSize(
R.dimen.notification_collapse_second_card_padding);
mBottomStackIndentationFunctor = new PiecewiseLinearIndentationFunctor(
MAX_ITEMS_IN_BOTTOM_STACK,
mBottomStackPeekSize,
@@ -508,7 +501,7 @@ public class StackScrollAlgorithm {
int childHeight, int minHeight, AmbientState ambientState) {
int bottomStackStart = ambientState.getInnerHeight()
- mBottomStackPeekSize - mCollapseSecondCardPadding;
- mBottomStackPeekSize - mBottomStackSlowDownLength;
int childStart = bottomStackStart - childHeight;
if (childStart < childViewState.yTranslation) {
float newHeight = bottomStackStart - childViewState.yTranslation;
@@ -595,12 +588,9 @@ public class StackScrollAlgorithm {
// The starting position of the bottom stack peek
int bottomPeekStart = ambientState.getInnerHeight() - mBottomStackPeekSize -
mCollapseSecondCardPadding + ambientState.getScrollY();
mBottomStackSlowDownLength + ambientState.getScrollY();
// Collapse and expand the first child while the shade is being expanded
float maxHeight = mIsExpansionChanging && child == mFirstChildWhileExpanding
? mFirstChildMaxHeight
: childHeight;
childViewState.height = (int) Math.max(Math.min(bottomPeekStart, maxHeight),
childViewState.height = (int) Math.max(Math.min(bottomPeekStart, (float) childHeight),
child.getMinHeight());
}
@@ -656,55 +646,6 @@ public class StackScrollAlgorithm {
}
}
public void onExpansionStarted(StackScrollState currentState) {
mIsExpansionChanging = true;
mExpandedOnStart = mIsExpanded;
ViewGroup hostView = currentState.getHostView();
updateFirstChildHeightWhileExpanding(hostView);
}
private void updateFirstChildHeightWhileExpanding(ViewGroup hostView) {
mFirstChildWhileExpanding = (ExpandableView) findFirstVisibleChild(hostView);
if (mFirstChildWhileExpanding != null) {
if (mExpandedOnStart) {
// We are collapsing the shade, so the first child can get as most as high as the
// current height or the end value of the animation.
mFirstChildMaxHeight = StackStateAnimator.getFinalActualHeight(
mFirstChildWhileExpanding);
} else {
updateFirstChildMaxSizeToMaxHeight();
}
} else {
mFirstChildMaxHeight = 0;
}
}
private void updateFirstChildMaxSizeToMaxHeight() {
// We are expanding the shade, expand it to its full height.
if (!isMaxSizeInitialized(mFirstChildWhileExpanding)) {
// This child was not layouted yet, wait for a layout pass
mFirstChildWhileExpanding
.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right,
int bottom, int oldLeft, int oldTop, int oldRight,
int oldBottom) {
if (mFirstChildWhileExpanding != null) {
mFirstChildMaxHeight = getMaxAllowedChildHeight(
mFirstChildWhileExpanding);
} else {
mFirstChildMaxHeight = 0;
}
v.removeOnLayoutChangeListener(this);
}
});
} else {
mFirstChildMaxHeight = getMaxAllowedChildHeight(mFirstChildWhileExpanding);
}
}
private boolean isMaxSizeInitialized(ExpandableView child) {
if (child instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
@@ -724,32 +665,10 @@ public class StackScrollAlgorithm {
return null;
}
public void onExpansionStopped() {
mIsExpansionChanging = false;
mFirstChildWhileExpanding = null;
}
public void setIsExpanded(boolean isExpanded) {
this.mIsExpanded = isExpanded;
}
public void notifyChildrenChanged(final NotificationStackScrollLayout hostView) {
if (mIsExpansionChanging) {
hostView.post(new Runnable() {
@Override
public void run() {
updateFirstChildHeightWhileExpanding(hostView);
}
});
}
}
public void onReset(ExpandableView view) {
if (view.equals(mFirstChildWhileExpanding)) {
updateFirstChildMaxSizeToMaxHeight();
}
}
class StackScrollAlgorithmState {
/**