Fix bottom hun content position

Clip bottom instead of top
and so we don't have to move the notification up.

Fixes: 224790257
Bug: 200544499
Test: send tall hun with actions, then send short hun
      swipe short hun => see hun below has contents at correct y

Change-Id: Ib32173a2e41fa4f693eab44368458117f6d1ca47
This commit is contained in:
Lyn Han
2022-04-01 11:04:35 -04:00
parent 16ba50d5f5
commit c328f06cdc
4 changed files with 76 additions and 43 deletions

View File

@@ -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"/>

View File

@@ -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());

View File

@@ -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,11 +99,16 @@ 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
*/
@@ -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);
}
/**

View File

@@ -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