diff options
4 files changed, 76 insertions, 43 deletions
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml index 926734c2749f..ff71b4f5e405 100644 --- a/packages/SystemUI/res/values/ids.xml +++ b/packages/SystemUI/res/values/ids.xml @@ -23,6 +23,7 @@ <item type="id" name="scale_x_animator_tag"/> <item type="id" name="scale_y_animator_tag"/> <item type="id" name="top_inset_animator_tag"/> + <item type="id" name="bottom_inset_animator_tag"/> <item type="id" name="height_animator_tag"/> <item type="id" name="x_animator_tag"/> <item type="id" name="y_animator_tag"/> @@ -33,6 +34,7 @@ <item type="id" name="scale_y_animator_end_value_tag"/> <item type="id" name="alpha_animator_end_value_tag"/> <item type="id" name="top_inset_animator_end_value_tag"/> + <item type="id" name="bottom_inset_animator_end_value_tag"/> <item type="id" name="height_animator_end_value_tag"/> <item type="id" name="x_animator_tag_end_value"/> <item type="id" name="y_animator_tag_end_value"/> @@ -43,6 +45,7 @@ <item type="id" name="scale_y_animator_start_value_tag"/> <item type="id" name="alpha_animator_start_value_tag"/> <item type="id" name="top_inset_animator_start_value_tag"/> + <item type="id" name="bottom_inset_animator_start_value_tag"/> <item type="id" name="height_animator_start_value_tag"/> <item type="id" name="x_animator_tag_start_value"/> <item type="id" name="y_animator_tag_start_value"/> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java index eaa66bbc15ac..633786ffa787 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java @@ -594,16 +594,13 @@ public class NotificationShelf extends ActivatableNotificationView implements } else { shouldClipOwnTop = view.showingPulsing(); } - if (viewEnd > notificationClipEnd && !shouldClipOwnTop - && (mAmbientState.isShadeExpanded() || !isPinned)) { - int clipBottomAmount = (int) (viewEnd - notificationClipEnd); - if (isPinned) { - clipBottomAmount = Math.min(view.getIntrinsicHeight() - view.getCollapsedHeight(), - clipBottomAmount); + if (!isPinned) { + if (viewEnd > notificationClipEnd && !shouldClipOwnTop) { + int clipBottomAmount = (int) (viewEnd - notificationClipEnd); + view.setClipBottomAmount(clipBottomAmount); + } else { + view.setClipBottomAmount(0); } - view.setClipBottomAmount(clipBottomAmount); - } else { - view.setClipBottomAmount(0); } if (shouldClipOwnTop) { return (int) (viewEnd - getTranslationY()); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ExpandableViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ExpandableViewState.java index b95d153e8bd1..7f3381ccd38a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ExpandableViewState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ExpandableViewState.java @@ -34,10 +34,13 @@ public class ExpandableViewState extends ViewState { private static final int TAG_ANIMATOR_HEIGHT = R.id.height_animator_tag; private static final int TAG_ANIMATOR_TOP_INSET = R.id.top_inset_animator_tag; + private static final int TAG_ANIMATOR_BOTTOM_INSET = R.id.bottom_inset_animator_tag; private static final int TAG_END_HEIGHT = R.id.height_animator_end_value_tag; private static final int TAG_END_TOP_INSET = R.id.top_inset_animator_end_value_tag; + private static final int TAG_END_BOTTOM_INSET = R.id.bottom_inset_animator_end_value_tag; private static final int TAG_START_HEIGHT = R.id.height_animator_start_value_tag; private static final int TAG_START_TOP_INSET = R.id.top_inset_animator_start_value_tag; + private static final int TAG_START_BOTTOM_INSET = R.id.bottom_inset_animator_start_value_tag; // These are flags such that we can create masks for filtering. @@ -96,12 +99,17 @@ public class ExpandableViewState extends ViewState { public boolean headsUpIsVisible; /** - * How much the child overlaps with the previous child on top. This is used to - * show the background properly when the child on top is translating away. + * How much the child overlaps on top with the child above. */ public int clipTopAmount; /** + * How much the child overlaps on bottom with the child above. This is used to + * show the background properly when the child on top is translating away. + */ + public int clipBottomAmount; + + /** * The index of the view, only accounting for views not equal to GONE */ public int notGoneIndex; @@ -138,8 +146,8 @@ public class ExpandableViewState extends ViewState { if (view instanceof ExpandableView) { ExpandableView expandableView = (ExpandableView) view; - int height = expandableView.getActualHeight(); - int newHeight = this.height; + final int height = expandableView.getActualHeight(); + final int newHeight = this.height; // apply height if (height != newHeight) { @@ -157,10 +165,14 @@ public class ExpandableViewState extends ViewState { expandableView.setBelowSpeedBump(this.belowSpeedBump); // apply clipping - float oldClipTopAmount = expandableView.getClipTopAmount(); + final float oldClipTopAmount = expandableView.getClipTopAmount(); if (oldClipTopAmount != this.clipTopAmount) { expandableView.setClipTopAmount(this.clipTopAmount); } + final float oldClipBottomAmount = expandableView.getClipBottomAmount(); + if (oldClipBottomAmount != this.clipBottomAmount) { + expandableView.setClipBottomAmount(this.clipBottomAmount); + } expandableView.setTransformingInShelf(false); expandableView.setInShelf(inShelf); @@ -187,13 +199,20 @@ public class ExpandableViewState extends ViewState { abortAnimation(child, TAG_ANIMATOR_HEIGHT); } - // start top inset animation + // start clip top animation if (this.clipTopAmount != expandableView.getClipTopAmount()) { - startInsetAnimation(expandableView, properties); + startClipAnimation(expandableView, properties, /* clipTop */true); } else { abortAnimation(child, TAG_ANIMATOR_TOP_INSET); } + // start clip bottom animation + if (this.clipBottomAmount != expandableView.getClipBottomAmount()) { + startClipAnimation(expandableView, properties, /* clipTop */ false); + } else { + abortAnimation(child, TAG_ANIMATOR_BOTTOM_INSET); + } + // start dimmed animation expandableView.setDimmed(this.dimmed, animationFilter.animateDimmed); @@ -301,16 +320,20 @@ public class ExpandableViewState extends ViewState { child.setActualHeightAnimating(true); } - private void startInsetAnimation(final ExpandableView child, AnimationProperties properties) { - Integer previousStartValue = getChildTag(child, TAG_START_TOP_INSET); - Integer previousEndValue = getChildTag(child, TAG_END_TOP_INSET); - int newEndValue = this.clipTopAmount; + private void startClipAnimation(final ExpandableView child, AnimationProperties properties, + boolean clipTop) { + Integer previousStartValue = getChildTag(child, + clipTop ? TAG_START_TOP_INSET : TAG_START_BOTTOM_INSET); + Integer previousEndValue = getChildTag(child, + clipTop ? TAG_END_TOP_INSET : TAG_END_BOTTOM_INSET); + int newEndValue = clipTop ? this.clipTopAmount : this.clipBottomAmount; if (previousEndValue != null && previousEndValue == newEndValue) { return; } - ValueAnimator previousAnimator = getChildTag(child, TAG_ANIMATOR_TOP_INSET); + ValueAnimator previousAnimator = getChildTag(child, + clipTop ? TAG_ANIMATOR_TOP_INSET : TAG_ANIMATOR_BOTTOM_INSET); AnimationFilter filter = properties.getAnimationFilter(); - if (!filter.animateTopInset) { + if (clipTop && !filter.animateTopInset || !clipTop) { // just a local update was performed if (previousAnimator != null) { // we need to increase all animation keyframes of the previous animator by the @@ -319,22 +342,28 @@ public class ExpandableViewState extends ViewState { int relativeDiff = newEndValue - previousEndValue; int newStartValue = previousStartValue + relativeDiff; values[0].setIntValues(newStartValue, newEndValue); - child.setTag(TAG_START_TOP_INSET, newStartValue); - child.setTag(TAG_END_TOP_INSET, newEndValue); + child.setTag(clipTop ? TAG_START_TOP_INSET : TAG_START_BOTTOM_INSET, newStartValue); + child.setTag(clipTop ? TAG_END_TOP_INSET : TAG_END_BOTTOM_INSET, newEndValue); previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime()); return; } else { // no new animation needed, let's just apply the value - child.setClipTopAmount(newEndValue); + if (clipTop) { + child.setClipTopAmount(newEndValue); + } else { + child.setClipBottomAmount(newEndValue); + } return; } } - ValueAnimator animator = ValueAnimator.ofInt(child.getClipTopAmount(), newEndValue); - animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { + ValueAnimator animator = ValueAnimator.ofInt( + clipTop ? child.getClipTopAmount() : child.getClipBottomAmount(), newEndValue); + animator.addUpdateListener(animation -> { + if (clipTop) { child.setClipTopAmount((int) animation.getAnimatedValue()); + } else { + child.setClipBottomAmount((int) animation.getAnimatedValue()); } }); animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN); @@ -353,15 +382,16 @@ public class ExpandableViewState extends ViewState { animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - child.setTag(TAG_ANIMATOR_TOP_INSET, null); - child.setTag(TAG_START_TOP_INSET, null); - child.setTag(TAG_END_TOP_INSET, null); + child.setTag(clipTop ? TAG_ANIMATOR_TOP_INSET : TAG_ANIMATOR_BOTTOM_INSET, null); + child.setTag(clipTop ? TAG_START_TOP_INSET : TAG_START_BOTTOM_INSET, null); + child.setTag(clipTop ? TAG_END_TOP_INSET : TAG_END_BOTTOM_INSET, null); } }); startAnimator(animator, listener); - child.setTag(TAG_ANIMATOR_TOP_INSET, animator); - child.setTag(TAG_START_TOP_INSET, child.getClipTopAmount()); - child.setTag(TAG_END_TOP_INSET, newEndValue); + child.setTag(clipTop ? TAG_ANIMATOR_TOP_INSET:TAG_ANIMATOR_BOTTOM_INSET, animator); + child.setTag(clipTop ? TAG_START_TOP_INSET: TAG_START_BOTTOM_INSET, + clipTop ? child.getClipTopAmount() : child.getClipBottomAmount()); + child.setTag(clipTop ? TAG_END_TOP_INSET: TAG_END_BOTTOM_INSET, newEndValue); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java index e1f8c35c3755..c0971337a19f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java @@ -192,6 +192,7 @@ public class StackScrollAlgorithm { float clipStart = 0; int childCount = algorithmState.visibleChildren.size(); boolean firstHeadsUp = true; + float firstHeadsUpEnd = 0; for (int i = 0; i < childCount; i++) { ExpandableView child = algorithmState.visibleChildren.get(i); ExpandableViewState state = child.getViewState(); @@ -203,14 +204,18 @@ public class StackScrollAlgorithm { float newNotificationEnd = newYTranslation + newHeight; boolean isHeadsUp = (child instanceof ExpandableNotificationRow) && child.isPinned(); if (mClipNotificationScrollToTop - && (!state.inShelf || (isHeadsUp && !firstHeadsUp)) - && newYTranslation < clipStart + && ((isHeadsUp && !firstHeadsUp) || child.isHeadsUpAnimatingAway()) + && newNotificationEnd > firstHeadsUpEnd && !ambientState.isShadeExpanded()) { - // The previous view is overlapping on top, clip! - float overlapAmount = clipStart - newYTranslation; - state.clipTopAmount = (int) overlapAmount; + // The bottom of this view is peeking out from under the previous view. + // Clip the part that is peeking out. + float overlapAmount = newNotificationEnd - firstHeadsUpEnd; + state.clipBottomAmount = (int) overlapAmount; } else { - state.clipTopAmount = 0; + state.clipBottomAmount = 0; + } + if (firstHeadsUp) { + firstHeadsUpEnd = newNotificationEnd; } if (isHeadsUp) { firstHeadsUp = false; @@ -635,8 +640,6 @@ public class StackScrollAlgorithm { // Ensure that a headsUp doesn't vertically extend further than the heads-up at // the top most z-position childState.height = row.getIntrinsicHeight(); - childState.yTranslation = Math.min(topState.yTranslation + topState.height - - childState.height, childState.yTranslation); } // heads up notification show and this row is the top entry of heads up |