Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c328f06c authored by Lyn Han's avatar Lyn Han
Browse files

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
parent 16ba50d5
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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"/>
+6 −9
Original line number Diff line number Diff line
@@ -594,17 +594,14 @@ public class NotificationShelf extends ActivatableNotificationView implements
        } else {
            shouldClipOwnTop = view.showingPulsing();
        }
        if (viewEnd > notificationClipEnd && !shouldClipOwnTop
                && (mAmbientState.isShadeExpanded() || !isPinned)) {
        if (!isPinned) {
            if (viewEnd > notificationClipEnd && !shouldClipOwnTop) {
                int clipBottomAmount = (int) (viewEnd - notificationClipEnd);
            if (isPinned) {
                clipBottomAmount = Math.min(view.getIntrinsicHeight() - view.getCollapsedHeight(),
                        clipBottomAmount);
            }
                view.setClipBottomAmount(clipBottomAmount);
            } else {
                view.setClipBottomAmount(0);
            }
        }
        if (shouldClipOwnTop) {
            return (int) (viewEnd - getTranslationY());
        } else {
+56 −26
Original line number Diff line number Diff line
@@ -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
                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);
    }

    /**
+11 −8
Original line number Diff line number Diff line
@@ -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