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

Commit 4f11fba0 authored by Yining Liu's avatar Yining Liu
Browse files

Right-align short shelf for split shade when minimalism enabled

Align the short shelf to the right (left when RTL) side for split shade
on lock screen when the notification minimalism is enabled.

Bug: 357643925
Flag: com.android.server.notification.notification_minimalism
Test: manual, verify split shade on lock screen
Change-Id: I7129529ef9382c2c9bb7d7a63e0b7b7e255643fb
parent 222084ca
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -24,11 +24,11 @@
    android:clickable="true"
    >

    <com.android.systemui.statusbar.notification.row.NotificationBackgroundView
    <com.android.systemui.statusbar.notification.shelf.NotificationShelfBackgroundView
        android:id="@+id/backgroundNormal"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <com.android.systemui.statusbar.phone.NotificationIconContainer
    <com.android.systemui.statusbar.notification.shelf.NotificationShelfIconContainer
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
+72 −6
Original line number Diff line number Diff line
@@ -48,6 +48,9 @@ import com.android.systemui.statusbar.notification.SourceType;
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.shared.NotificationMinimalism;
import com.android.systemui.statusbar.notification.shelf.NotificationShelfBackgroundView;
import com.android.systemui.statusbar.notification.shelf.NotificationShelfIconContainer;
import com.android.systemui.statusbar.notification.stack.AmbientState;
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
@@ -76,7 +79,9 @@ public class NotificationShelf extends ActivatableNotificationView {
    private static final SourceType BASE_VALUE = SourceType.from("BaseValue");
    private static final SourceType SHELF_SCROLL = SourceType.from("ShelfScroll");

    private NotificationIconContainer mShelfIcons;
    private NotificationShelfIconContainer mShelfIcons;
    // This field hides mBackgroundNormal from super class for short-shelf alignment
    private NotificationShelfBackgroundView mBackgroundNormal;
    private boolean mHideBackground;
    private int mStatusBarHeight;
    private boolean mEnableNotificationClipping;
@@ -116,6 +121,8 @@ public class NotificationShelf extends ActivatableNotificationView {
        mShelfIcons.setClipChildren(false);
        mShelfIcons.setClipToPadding(false);

        mBackgroundNormal = (NotificationShelfBackgroundView) super.mBackgroundNormal;

        setClipToActualHeight(false);
        setClipChildren(false);
        setClipToPadding(false);
@@ -271,16 +278,30 @@ public class NotificationShelf extends ActivatableNotificationView {
    private void setActualWidth(float actualWidth) {
        setBackgroundWidth((int) actualWidth);
        if (mShelfIcons != null) {
            mShelfIcons.setAlignToEnd(isAlignedToEnd());
            mShelfIcons.setActualLayoutWidth((int) actualWidth);
        }
        mActualWidth = actualWidth;
    }

    @Override
    public void setBackgroundWidth(int width) {
        super.setBackgroundWidth(width);
        if (!NotificationMinimalism.isEnabled()) {
            return;
        }
        if (mBackgroundNormal != null) {
            mBackgroundNormal.setAlignToEnd(isAlignedToEnd());
        }
    }

    @Override
    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
        super.getBoundsOnScreen(outRect, clipToParent);
        final int actualWidth = getActualWidth();
        if (isLayoutRtl()) {
        final boolean alignedToRight = NotificationMinimalism.isEnabled() ? isAlignedToRight() :
                isLayoutRtl();
        if (alignedToRight) {
            outRect.left = outRect.right - actualWidth;
        } else {
            outRect.right = outRect.left + actualWidth;
@@ -326,11 +347,17 @@ public class NotificationShelf extends ActivatableNotificationView {
     */
    @Override
    public boolean pointInView(float localX, float localY, float slop) {
        final float left, right;

        if (NotificationMinimalism.isEnabled()) {
            left = getShelfLeftBound();
            right = getShelfRightBound();
        } else {
            final float containerWidth = getWidth();
            final float shelfWidth = getActualWidth();

        final float left = isLayoutRtl() ? containerWidth - shelfWidth : 0;
        final float right = isLayoutRtl() ? containerWidth : shelfWidth;
            left = isLayoutRtl() ? containerWidth - shelfWidth : 0;
            right = isLayoutRtl() ? containerWidth : shelfWidth;
        }

        final float top = mClipTopAmount;
        final float bottom = getActualHeight();
@@ -339,10 +366,49 @@ public class NotificationShelf extends ActivatableNotificationView {
                && isYInView(localY, slop, top, bottom);
    }

    /**
     * @return The left boundary of the shelf.
     */
    private float getShelfLeftBound() {
        if (isAlignedToRight()) {
            return getWidth() - getActualWidth();
        } else {
            return 0;
        }
    }

    /**
     * @return The right boundary of the shelf.
     */
    private float getShelfRightBound() {
        if (isAlignedToRight()) {
            return getWidth();
        } else {
            return getActualWidth();
        }
    }

    private boolean isAlignedToRight() {
        return isAlignedToEnd() ^ isLayoutRtl();
    }

    /**
     * When notification minimalism is on, on split shade, we want the notification shelf to align
     * to the layout end (right for LTR; left for RTL).
     * @return whether to align with the minimalism split shade style
     */
    private boolean isAlignedToEnd() {
        if (!NotificationMinimalism.isEnabled()) {
            return false;
        }
        return mAmbientState.getUseSplitShade();
    }

    @Override
    public void updateBackgroundColors() {
        super.updateBackgroundColors();
        ColorUpdateLogger colorUpdateLogger = ColorUpdateLogger.getInstance();

        if (colorUpdateLogger != null) {
            colorUpdateLogger.logEvent("Shelf.updateBackgroundColors()",
                    "normalBgColor=" + hexColorString(getNormalBgColor())
+16 −6
Original line number Diff line number Diff line
@@ -169,12 +169,12 @@ public class NotificationBackgroundView extends View implements Dumpable,
                && !mExpandAnimationRunning) {
            bottom -= mClipBottomAmount;
        }
        final boolean isRtl = isLayoutRtl();
        final boolean alignedToRight = isAlignedToRight();
        final int width = getWidth();
        final int actualWidth = getActualWidth();

        int left = isRtl ? width - actualWidth : 0;
        int right = isRtl ? width : actualWidth;
        int left = alignedToRight ? width - actualWidth : 0;
        int right = alignedToRight ? width : actualWidth;

        if (mExpandAnimationRunning) {
            // Horizontally center this background view inside of the container
@@ -185,6 +185,15 @@ public class NotificationBackgroundView extends View implements Dumpable,
        return new Rect(left, top, right, bottom);
    }

    /**
     * @return Whether the background view should be right-aligned. This only matters if the
     * actualWidth is different than the full (measured) width. In other words, this is used to
     * define the short-shelf alignment.
     */
    protected boolean isAlignedToRight() {
        return isLayoutRtl();
    }

    private void draw(Canvas canvas, Drawable drawable) {
        NotificationAddXOnHoverToDismiss.assertInLegacyMode();

@@ -196,12 +205,13 @@ public class NotificationBackgroundView extends View implements Dumpable,
                    && !mExpandAnimationRunning) {
                bottom -= mClipBottomAmount;
            }
            final boolean isRtl = isLayoutRtl();

            final boolean alignedToRight = isAlignedToRight();
            final int width = getWidth();
            final int actualWidth = getActualWidth();

            int left = isRtl ? width - actualWidth : 0;
            int right = isRtl ? width : actualWidth;
            int left = alignedToRight ? width - actualWidth : 0;
            int right = alignedToRight ? width : actualWidth;

            if (mExpandAnimationRunning) {
                // Horizontally center this background view inside of the container
+44 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.statusbar.notification.shelf

import android.content.Context
import android.util.AttributeSet
import com.android.systemui.statusbar.notification.row.NotificationBackgroundView
import com.android.systemui.statusbar.notification.shared.NotificationMinimalism

/** The background view for the NotificationShelf. */
class NotificationShelfBackgroundView
@JvmOverloads
constructor(context: Context, attrs: AttributeSet? = null) :
    NotificationBackgroundView(context, attrs) {

    /** Whether the notification shelf is aligned to end, need to keep persistent with the shelf. */
    var alignToEnd = false

    /** @return whether the alignment of the notification shelf is right. */
    override fun isAlignedToRight(): Boolean {
        if (!NotificationMinimalism.isEnabled) {
            return super.isAlignedToRight()
        }
        return alignToEnd xor isLayoutRtl
    }

    override fun toDumpString(): String {
        return super.toDumpString() + " alignToEnd=" + alignToEnd
    }
}
+90 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.statusbar.notification.shelf

import android.content.Context
import android.util.AttributeSet
import android.view.View
import com.android.systemui.statusbar.notification.shared.NotificationMinimalism
import com.android.systemui.statusbar.phone.NotificationIconContainer
import kotlin.math.max

/** The NotificationIconContainer for the NotificationShelf. */
class NotificationShelfIconContainer
@JvmOverloads
constructor(context: Context, attrs: AttributeSet? = null) :
    NotificationIconContainer(context, attrs) {

    /** Whether the notification shelf is aligned to end. */
    var alignToEnd = false

    /**
     * @return The left boundary (not the RTL compatible start) of the area that icons can be added.
     */
    override fun getLeftBound(): Float {
        if (!NotificationMinimalism.isEnabled) {
            return super.getLeftBound()
        }

        if (isAlignedToRight) {
            return (max(width - actualWidth, 0) + actualPaddingStart)
        }
        return actualPaddingStart
    }

    /**
     * @return The right boundary (not the RTL compatible end) of the area that icons can be added.
     */
    override fun getRightBound(): Float {
        if (!NotificationMinimalism.isEnabled) {
            return super.getRightBound()
        }

        if (isAlignedToRight) {
            return width - actualPaddingEnd
        }
        return actualWidth - actualPaddingEnd
    }

    /**
     * For RTL, the icons' x positions should be mirrored around the middle of the shelf so that the
     * icons are also added to the shelf from right to left. This function should only be called
     * when RTL.
     */
    override fun getRtlIconTranslationX(iconState: IconState, iconView: View): Float {
        if (!NotificationMinimalism.isEnabled) {
            return super.getRtlIconTranslationX(iconState, iconView)
        }

        if (!isLayoutRtl) {
            return iconState.xTranslation
        }

        if (isAlignedToRight) {
            return width * 2 - actualWidth - iconState.xTranslation - iconView.width
        }
        return actualWidth - iconState.xTranslation - iconView.width
    }

    private val isAlignedToRight: Boolean
        get() {
            if (!NotificationMinimalism.isEnabled) {
                return isLayoutRtl
            }
            return alignToEnd xor isLayoutRtl
        }
}
Loading