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

Commit e2d6f040 authored by Gus Prevas's avatar Gus Prevas
Browse files

Adds gap after high-priority notifications.

This change adds a gap between notifications of IMPORTANCE_DEFAULT or
higher and all other notificaitons.  The position of the gap is
recalculated from NotificationPanelView.updateNotificationViews() and
the various components which handle the rounded corners of the
notification shade (NotificationRoundnessManager, the shelf, and the
drawBackground() method in NotificationStackScrollLayout) are updated to
handle rounding the corners on either side of the gap.

Change-Id: Ib8d875d4b82184c9c4d363669606261030a467c8
Bug: 116622974
Test: atest SystemUITests
parent 1fa34b08
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -478,6 +478,9 @@
    <!-- The height of the divider between the individual notifications when the notification wants it to be increased. This is currently the case for notification groups -->
    <dimen name="notification_divider_height_increased">6dp</dimen>

    <!-- The height of the gap between adjacent notification sections. -->
    <dimen name="notification_section_divider_height">@dimen/notification_side_paddings</dimen>

    <!-- The minimum amount of top overscroll to go to the quick settings. -->
    <dimen name="min_top_overscroll_to_qs">36dp</dimen>

+22 −0
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
    private float mFirstElementRoundness;
    private Rect mClipRect = new Rect();
    private int mCutoutHeight;
    private int mGapHeight;

    private final StateListener mStateListener = this::setStatusBarState;

@@ -154,6 +155,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
        mScrollFastThreshold = res.getDimensionPixelOffset(R.dimen.scroll_fast_threshold);
        mShowNotificationShelf = res.getBoolean(R.bool.config_showNotificationShelf);
        mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size);
        mGapHeight = res.getDimensionPixelSize(R.dimen.qs_notification_padding);

        if (!mShowNotificationShelf) {
            setVisibility(GONE);
@@ -276,6 +278,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
        int baseZHeight = mAmbientState.getBaseZHeight();
        int backgroundTop = 0;
        float firstElementRoundness = 0.0f;
        ExpandableNotificationRow previousRow = null;

        for (int i = 0; i < mHostLayout.getChildCount(); i++) {
            ExpandableView child = (ExpandableView) mHostLayout.getChildAt(i);
@@ -343,8 +346,27 @@ public class NotificationShelf extends ActivatableNotificationView implements
                            + " \n number of notifications: " + mHostLayout.getChildCount() );
                }
            }
            if (row.isFirstInSection() && previousRow != null && previousRow.isLastInSection()) {
                // If the top of the shelf is between the view before a gap and the view after a gap
                // then we need to adjust the shelf's top roundness.
                float distanceToGapBottom = row.getTranslationY() - getTranslationY();
                float distanceToGapTop = getTranslationY()
                        - (previousRow.getTranslationY() + previousRow.getActualHeight());
                if (distanceToGapTop > 0) {
                    // We interpolate our top roundness so that it's fully rounded if we're at the
                    // bottom of the gap, and not rounded at all if we're at the top of the gap
                    // (directly up against the bottom of previousRow)
                    // Then we apply the same roundness to the bottom of previousRow so that the
                    // corners join together as the shelf approaches previousRow.
                    firstElementRoundness = (float) Math.min(1.0, distanceToGapTop / mGapHeight);
                    previousRow.setBottomRoundness(firstElementRoundness,
                            false /* don't animate */);
                    backgroundTop = (int) distanceToGapBottom;
                }
            }
            notGoneIndex++;
            previousColor = ownColorUntinted;
            previousRow = row;
        }

        clipTransientViews();
+29 −1
Original line number Diff line number Diff line
@@ -40,9 +40,9 @@ import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.notification.FakeShadowView;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.phone.DoubleTapHelper;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.DoubleTapHelper;

/**
 * Base class for both {@link ExpandableNotificationRow} and {@link NotificationShelf}
@@ -134,6 +134,8 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
    private float mAppearAnimationFraction = -1.0f;
    private float mAppearAnimationTranslation;
    private int mNormalColor;
    private boolean mLastInSection;
    private boolean mFirstInSection;
    private boolean mIsBelowSpeedBump;
    private FalsingManager mFalsingManager;

@@ -533,6 +535,32 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
        mBackgroundDimmed.setDistanceToTopRoundness(distanceToTopRoundness);
    }

    public boolean isLastInSection() {
        return mLastInSection;
    }

    public boolean isFirstInSection() {
        return mFirstInSection;
    }

    /** Sets whether this view is the last notification in a section. */
    public void setLastInSection(boolean lastInSection) {
        if (lastInSection != mLastInSection) {
            mLastInSection = lastInSection;
            mBackgroundNormal.setLastInSection(lastInSection);
            mBackgroundDimmed.setLastInSection(lastInSection);
        }
    }

    /** Sets whether this view is the first notification in a section. */
    public void setFirstInSection(boolean firstInSection) {
        if (firstInSection != mFirstInSection) {
            mFirstInSection = firstInSection;
            mBackgroundNormal.setFirstInSection(firstInSection);
            mBackgroundDimmed.setFirstInSection(firstInSection);
        }
    }

    /**
     * Set an override tint color that is used for the background.
     *
+33 −10
Original line number Diff line number Diff line
@@ -46,6 +46,8 @@ public class NotificationBackgroundView extends View {
    private int mTintColor;
    private float[] mCornerRadii = new float[8];
    private boolean mBottomIsRounded;
    private boolean mLastInSection;
    private boolean mFirstInSection;
    private int mBackgroundTop;
    private boolean mBottomAmountClips = true;
    private boolean mExpandAnimationRunning;
@@ -79,7 +81,10 @@ public class NotificationBackgroundView extends View {
        if (drawable != null) {
            int top = mBackgroundTop;
            int bottom = mActualHeight;
            if (mBottomIsRounded && mBottomAmountClips && !mExpandAnimationRunning) {
            if (mBottomIsRounded
                    && mBottomAmountClips
                    && !mExpandAnimationRunning
                    && !mLastInSection) {
                bottom -= mClipBottomAmount;
            }
            int left = 0;
@@ -90,8 +95,10 @@ public class NotificationBackgroundView extends View {
            }
            if (mTopAmountRounded) {
                int clipTop = (int) (mClipTopAmount - mDistanceToTopRoundness);
                if (clipTop >= 0 || !mFirstInSection) {
                    top += clipTop;
                if (clipTop >= 0) {
                }
                if (clipTop >= 0 && !mLastInSection) {
                    bottom += clipTop;
                }
            }
@@ -216,19 +223,23 @@ public class NotificationBackgroundView extends View {
        mBackground.setAlpha(drawableAlpha);
    }

    public void setRoundness(float topRoundness, float bottomRoundNess) {
        if (topRoundness == mCornerRadii[0] && bottomRoundNess == mCornerRadii[4]) {
    /**
     * Sets the current top and bottom roundness amounts for this background, between 0.0 (not
     * rounded) and 1.0 (maximally rounded).
     */
    public void setRoundness(float topRoundness, float bottomRoundness) {
        if (topRoundness == mCornerRadii[0] && bottomRoundness == mCornerRadii[4]) {
            return;
        }
        mBottomIsRounded = bottomRoundNess != 0.0f;
        mBottomIsRounded = bottomRoundness != 0.0f;
        mCornerRadii[0] = topRoundness;
        mCornerRadii[1] = topRoundness;
        mCornerRadii[2] = topRoundness;
        mCornerRadii[3] = topRoundness;
        mCornerRadii[4] = bottomRoundNess;
        mCornerRadii[5] = bottomRoundNess;
        mCornerRadii[6] = bottomRoundNess;
        mCornerRadii[7] = bottomRoundNess;
        mCornerRadii[4] = bottomRoundness;
        mCornerRadii[5] = bottomRoundness;
        mCornerRadii[6] = bottomRoundness;
        mCornerRadii[7] = bottomRoundness;
        updateBackgroundRadii();
    }

@@ -239,6 +250,18 @@ public class NotificationBackgroundView extends View {
        }
    }

    /** Sets whether this background belongs to the last notification in a section. */
    public void setLastInSection(boolean lastInSection) {
        mLastInSection = lastInSection;
        invalidate();
    }

    /** Sets whether this background belongs to the first notification in a section. */
    public void setFirstInSection(boolean firstInSection) {
        mFirstInSection = firstInSection;
        invalidate();
    }

    private void updateBackgroundRadii() {
        if (mDontModifyCorners) {
            return;
+31 −4
Original line number Diff line number Diff line
@@ -22,27 +22,32 @@ import android.view.View;

import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.AmbientPulseManager;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.NotificationShelf;

import java.util.ArrayList;
import java.util.List;

/**
 * A global state to track all input states for the algorithm.
 */
public class AmbientState {
    private ArrayList<View> mDraggedViews = new ArrayList<View>();

    private static final int NO_SECTION_BOUNDARY = -1;

    private ArrayList<View> mDraggedViews = new ArrayList<>();
    private int mScrollY;
    private boolean mDimmed;
    private ActivatableNotificationView mActivatedChild;
    private float mOverScrollTopAmount;
    private float mOverScrollBottomAmount;
    private int mSpeedBumpIndex = -1;
    private final List<Integer> mSectionBoundaryIndices = new ArrayList<>();
    private boolean mDark;
    private boolean mHideSensitive;
    private AmbientPulseManager mAmbientPulseManager = Dependency.get(AmbientPulseManager.class);
@@ -75,6 +80,7 @@ public class AmbientState {
    private boolean mAppearing;

    public AmbientState(Context context) {
        mSectionBoundaryIndices.add(NO_SECTION_BOUNDARY);
        reload(context);
    }

@@ -208,6 +214,27 @@ public class AmbientState {
        mSpeedBumpIndex = shelfIndex;
    }

    /**
     * Returns the index of the boundary between two sections, where the first section is at index
     * {@code boundaryNum}.
     */
    public int getSectionBoundaryIndex(int boundaryNum) {
        return mSectionBoundaryIndices.get(boundaryNum);
    }

    /** Returns true if the item at {@code index} is directly below a section boundary. */
    public boolean beginsNewSection(int index) {
        return mSectionBoundaryIndices.contains(index);
    }

    /**
     * Sets the index of the boundary between the section at {@code boundaryNum} and the following
     * section to {@code boundaryIndex}.
     */
    public void setSectionBoundaryIndex(int boundaryNum, int boundaryIndex) {
        mSectionBoundaryIndices.set(boundaryNum, boundaryIndex);
    }

    public float getStackTranslation() {
        return mStackTranslation;
    }
Loading