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

Commit fb5e2407 authored by Selim Cinek's avatar Selim Cinek
Browse files

Fixed an issue where the notification clipping flickered

Because stopped clipping all views, the top views that were
scrolled could flicker on the screen during notification
launches

Fixes: 191470773
Test: add scrolled notification, launch, observe no flickering
Change-Id: Ia30abfdc6a46e8680bc336c3682ff5e35b0fb606
parent a1b3ce52
Loading
Loading
Loading
Loading
+16 −0
Original line number Original line Diff line number Diff line
@@ -22,11 +22,27 @@ class ExpandAnimationParameters(
    )
    )


    var startTranslationZ = 0f
    var startTranslationZ = 0f

    /**
     * The top position of the notification at the start of the animation. This is needed in order
     * to keep the notification at its place when launching a notification that is clipped rounded.
     */
    var startNotificationTop = 0f
    var startClipTopAmount = 0
    var startClipTopAmount = 0
    var parentStartClipTopAmount = 0
    var parentStartClipTopAmount = 0
    var progress = 0f
    var progress = 0f
    var linearProgress = 0f
    var linearProgress = 0f


    /**
     * The rounded top clipping at the beginning.
     */
    var startRoundedTopClipping = 0

    /**
     * The rounded top clipping of the parent notification at the start.
     */
    var parentStartRoundedTopClipping = 0

    override val topChange: Int
    override val topChange: Int
        get() {
        get() {
            // We need this compensation to ensure that the QS moves in sync.
            // We need this compensation to ensure that the QS moves in sync.
+26 −2
Original line number Original line Diff line number Diff line
@@ -40,6 +40,11 @@ class NotificationLaunchAnimatorController(
    private val headsUpManager: HeadsUpManagerPhone,
    private val headsUpManager: HeadsUpManagerPhone,
    private val notification: ExpandableNotificationRow
    private val notification: ExpandableNotificationRow
) : ActivityLaunchAnimator.Controller {
) : ActivityLaunchAnimator.Controller {

    companion object {
        const val ANIMATION_DURATION_TOP_ROUNDING = 100L
    }

    private val notificationEntry = notification.entry
    private val notificationEntry = notification.entry
    private val notificationKey = notificationEntry.sbn.key
    private val notificationKey = notificationEntry.sbn.key


@@ -54,18 +59,37 @@ class NotificationLaunchAnimatorController(
        val height = max(0, notification.actualHeight - notification.clipBottomAmount)
        val height = max(0, notification.actualHeight - notification.clipBottomAmount)
        val location = notification.locationOnScreen
        val location = notification.locationOnScreen


        val clipStartLocation = notificationListContainer.getTopClippingStartLocation()
        val roundedTopClipping = Math.max(clipStartLocation - location[1], 0)
        val windowTop = location[1] + roundedTopClipping
        val topCornerRadius = if (roundedTopClipping > 0) {
            // Because the rounded Rect clipping is complex, we start the top rounding at
            // 0, which is pretty close to matching the real clipping.
            // We'd have to clipOut the overlaid drawable too with the outer rounded rect in case
            // if we'd like to have this perfect, but this is close enough.
            0f
        } else {
            notification.currentBackgroundRadiusTop
        }
        val params = ExpandAnimationParameters(
        val params = ExpandAnimationParameters(
                top = location[1],
                top = windowTop,
                bottom = location[1] + height,
                bottom = location[1] + height,
                left = location[0],
                left = location[0],
                right = location[0] + notification.width,
                right = location[0] + notification.width,
                topCornerRadius = notification.currentBackgroundRadiusTop,
                topCornerRadius = topCornerRadius,
                bottomCornerRadius = notification.currentBackgroundRadiusBottom
                bottomCornerRadius = notification.currentBackgroundRadiusBottom
        )
        )


        params.startTranslationZ = notification.translationZ
        params.startTranslationZ = notification.translationZ
        params.startNotificationTop = notification.translationY
        params.startRoundedTopClipping = roundedTopClipping
        params.startClipTopAmount = notification.clipTopAmount
        params.startClipTopAmount = notification.clipTopAmount
        if (notification.isChildInGroup) {
        if (notification.isChildInGroup) {
            params.startNotificationTop += notification.notificationParent.translationY
            val parentRoundedClip = Math.max(clipStartLocation
                - notification.notificationParent.locationOnScreen[1], 0)
            params.parentStartRoundedTopClipping = parentRoundedClip

            val parentClip = notification.notificationParent.clipTopAmount
            val parentClip = notification.notificationParent.clipTopAmount
            params.parentStartClipTopAmount = parentClip
            params.parentStartClipTopAmount = parentClip


+41 −3
Original line number Original line Diff line number Diff line
@@ -35,6 +35,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.Path;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.AnimationDrawable;
@@ -85,6 +86,7 @@ import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.notification.AboveShelfChangedListener;
import com.android.systemui.statusbar.notification.AboveShelfChangedListener;
import com.android.systemui.statusbar.notification.ExpandAnimationParameters;
import com.android.systemui.statusbar.notification.ExpandAnimationParameters;
import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorController;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
@@ -252,6 +254,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
    private OnExpandClickListener mOnExpandClickListener;
    private OnExpandClickListener mOnExpandClickListener;
    private View.OnClickListener mOnAppClickListener;
    private View.OnClickListener mOnAppClickListener;
    private View.OnClickListener mOnFeedbackClickListener;
    private View.OnClickListener mOnFeedbackClickListener;
    private Path mExpandingClipPath;


    // Listener will be called when receiving a long click event.
    // Listener will be called when receiving a long click event.
    // Use #setLongPressPosition to optionally assign positional data with the long press.
    // Use #setLongPressPosition to optionally assign positional data with the long press.
@@ -836,6 +839,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
    public void setIsChildInGroup(boolean isChildInGroup, ExpandableNotificationRow parent) {
    public void setIsChildInGroup(boolean isChildInGroup, ExpandableNotificationRow parent) {
        if (mExpandAnimationRunning && !isChildInGroup && mNotificationParent != null) {
        if (mExpandAnimationRunning && !isChildInGroup && mNotificationParent != null) {
            mNotificationParent.setChildIsExpanding(false);
            mNotificationParent.setChildIsExpanding(false);
            mNotificationParent.setExpandingClipPath(null);
            mNotificationParent.setExtraWidthForClipping(0.0f);
            mNotificationParent.setExtraWidthForClipping(0.0f);
            mNotificationParent.setMinimumHeightForClipping(0);
            mNotificationParent.setMinimumHeightForClipping(0);
        }
        }
@@ -2036,7 +2040,22 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
        setTranslationZ(translationZ);
        setTranslationZ(translationZ);
        float extraWidthForClipping = params.getWidth() - getWidth();
        float extraWidthForClipping = params.getWidth() - getWidth();
        setExtraWidthForClipping(extraWidthForClipping);
        setExtraWidthForClipping(extraWidthForClipping);
        int top = params.getTop();
        int top;
        if (params.getStartRoundedTopClipping() > 0) {
            // If we were clipping initially, let's interpolate from the start position to the
            // top. Otherwise, we just take the top directly.
            float expandProgress = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(
                    params.getProgress(0,
                            NotificationLaunchAnimatorController.ANIMATION_DURATION_TOP_ROUNDING));
            float startTop = params.getStartNotificationTop();
            top = (int) Math.min(MathUtils.lerp(startTop,
                    params.getTop(), expandProgress),
                    startTop);
        } else {
            top = params.getTop();
        }
        int actualHeight = params.getBottom() - top;
        setActualHeight(actualHeight);
        int startClipTopAmount = params.getStartClipTopAmount();
        int startClipTopAmount = params.getStartClipTopAmount();
        int clipTopAmount = (int) MathUtils.lerp(startClipTopAmount, 0, params.getProgress());
        int clipTopAmount = (int) MathUtils.lerp(startClipTopAmount, 0, params.getProgress());
        if (mNotificationParent != null) {
        if (mNotificationParent != null) {
@@ -2065,13 +2084,12 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
            setClipTopAmount(clipTopAmount);
            setClipTopAmount(clipTopAmount);
        }
        }
        setTranslationY(top);
        setTranslationY(top);
        setActualHeight(params.getHeight());


        mTopRoundnessDuringExpandAnimation = params.getTopCornerRadius() / mOutlineRadius;
        mTopRoundnessDuringExpandAnimation = params.getTopCornerRadius() / mOutlineRadius;
        mBottomRoundnessDuringExpandAnimation = params.getBottomCornerRadius() / mOutlineRadius;
        mBottomRoundnessDuringExpandAnimation = params.getBottomCornerRadius() / mOutlineRadius;
        invalidateOutline();
        invalidateOutline();


        mBackgroundNormal.setExpandAnimationParams(params);
        mBackgroundNormal.setExpandAnimationSize(params.getWidth(), actualHeight);
    }
    }


    public void setExpandAnimationRunning(boolean expandAnimationRunning) {
    public void setExpandAnimationRunning(boolean expandAnimationRunning) {
@@ -3085,6 +3103,26 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
        return super.childNeedsClipping(child);
        return super.childNeedsClipping(child);
    }
    }


    /**
     * Set a clip path to be set while expanding the notification. This is needed to nicely
     * clip ourselves during the launch if we were clipped rounded in the beginning
     */
    public void setExpandingClipPath(Path path) {
        mExpandingClipPath = path;
        invalidate();
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        canvas.save();
        if (mExpandingClipPath != null && (mExpandAnimationRunning || mChildIsExpanding)) {
            // If we're launching a notification, let's clip if a clip rounded to the clipPath
            canvas.clipPath(mExpandingClipPath);
        }
        super.dispatchDraw(canvas);
        canvas.restore();
    }

    @Override
    @Override
    protected void applyRoundness() {
    protected void applyRoundness() {
        super.applyRoundness();
        super.applyRoundness();
+4 −4
Original line number Original line Diff line number Diff line
@@ -240,10 +240,10 @@ public class NotificationBackgroundView extends View {
        invalidate();
        invalidate();
    }
    }


    /** Set the current expand animation parameters. */
    /** Set the current expand animation size. */
    public void setExpandAnimationParams(ExpandAnimationParameters params) {
    public void setExpandAnimationSize(int actualWidth, int actualHeight) {
        mActualHeight = params.getHeight();
        mActualHeight = actualHeight;
        mActualWidth = params.getWidth();
        mActualWidth = actualWidth;
        invalidate();
        invalidate();
    }
    }


+0 −18
Original line number Original line Diff line number Diff line
@@ -72,8 +72,6 @@ public class AmbientState {
    private boolean mUnlockHintRunning;
    private boolean mUnlockHintRunning;
    private boolean mQsCustomizerShowing;
    private boolean mQsCustomizerShowing;
    private int mIntrinsicPadding;
    private int mIntrinsicPadding;
    private int mExpandAnimationTopChange;
    private ExpandableNotificationRow mExpandingNotification;
    private float mHideAmount;
    private float mHideAmount;
    private boolean mAppearing;
    private boolean mAppearing;
    private float mPulseHeight = MAX_PULSE_HEIGHT;
    private float mPulseHeight = MAX_PULSE_HEIGHT;
@@ -518,22 +516,6 @@ public class AmbientState {
        return isDozing() && !isPulsing(row.getEntry());
        return isDozing() && !isPulsing(row.getEntry());
    }
    }


    public void setExpandAnimationTopChange(int expandAnimationTopChange) {
        mExpandAnimationTopChange = expandAnimationTopChange;
    }

    public void setExpandingNotification(ExpandableNotificationRow row) {
        mExpandingNotification = row;
    }

    public ExpandableNotificationRow getExpandingNotification() {
        return mExpandingNotification;
    }

    public int getExpandAnimationTopChange() {
        return mExpandAnimationTopChange;
    }

    /**
    /**
     * @return {@code true } when shade is completely hidden: in AOD, ambient display or when
     * @return {@code true } when shade is completely hidden: in AOD, ambient display or when
     * bypassing.
     * bypassing.
Loading