diff options
6 files changed, 246 insertions, 22 deletions
diff --git a/packages/SystemUI/res/layout/status_bar_notification_shelf.xml b/packages/SystemUI/res/layout/status_bar_notification_shelf.xml index 58c545036b27..071b07631ff9 100644 --- a/packages/SystemUI/res/layout/status_bar_notification_shelf.xml +++ b/packages/SystemUI/res/layout/status_bar_notification_shelf.xml @@ -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" diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java index d523bc1867c2..044b5c8ff44f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java @@ -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 containerWidth = getWidth(); - final float shelfWidth = getActualWidth(); + final float left, right; - final float left = isLayoutRtl() ? containerWidth - shelfWidth : 0; - final float right = isLayoutRtl() ? containerWidth : shelfWidth; + if (NotificationMinimalism.isEnabled()) { + left = getShelfLeftBound(); + right = getShelfRightBound(); + } else { + final float containerWidth = getWidth(); + final float shelfWidth = getActualWidth(); + 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()) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java index e440d2728263..dd3a9c9dcf21 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java @@ -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 diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/NotificationShelfBackgroundView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/NotificationShelfBackgroundView.kt new file mode 100644 index 000000000000..62a3fd663e23 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/NotificationShelfBackgroundView.kt @@ -0,0 +1,44 @@ +/* + * 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 + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/NotificationShelfIconContainer.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/NotificationShelfIconContainer.kt new file mode 100644 index 000000000000..64d165402759 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/NotificationShelfIconContainer.kt @@ -0,0 +1,90 @@ +/* + * 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 + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java index ecd62bd6943b..c396512ce3a5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java @@ -198,7 +198,7 @@ public class NotificationIconContainer extends ViewGroup { Paint paint = new Paint(); paint.setColor(Color.RED); paint.setStyle(Paint.Style.STROKE); - canvas.drawRect(getActualPaddingStart(), 0, getLayoutEnd(), getHeight(), paint); + canvas.drawRect(getActualPaddingStart(), 0, getRightBound(), getHeight(), paint); if (DEBUG_OVERFLOW) { if (mLastVisibleIconState == null) { @@ -469,11 +469,11 @@ public class NotificationIconContainer extends ViewGroup { * If this is not a whole number, the fraction means by how much the icon is appearing. */ public void calculateIconXTranslations() { - float translationX = getActualPaddingStart(); + float translationX = getLeftBound(); int firstOverflowIndex = -1; int childCount = getChildCount(); int maxVisibleIcons = mMaxIcons; - float layoutEnd = getLayoutEnd(); + float layoutRight = getRightBound(); mVisualOverflowStart = 0; mFirstVisibleIconState = null; for (int i = 0; i < childCount; i++) { @@ -495,7 +495,7 @@ public class NotificationIconContainer extends ViewGroup { final boolean forceOverflow = shouldForceOverflow(i, mSpeedBumpIndex, iconState.iconAppearAmount, maxVisibleIcons); final boolean isOverflowing = forceOverflow || isOverflowing( - /* isLastChild= */ i == childCount - 1, translationX, layoutEnd, mIconSize); + /* isLastChild= */ i == childCount - 1, translationX, layoutRight, mIconSize); // First icon to overflow. if (firstOverflowIndex == -1 && isOverflowing) { @@ -536,8 +536,7 @@ public class NotificationIconContainer extends ViewGroup { for (int i = 0; i < childCount; i++) { View view = getChildAt(i); IconState iconState = mIconStates.get(view); - iconState.setXTranslation( - getWidth() - iconState.getXTranslation() - view.getWidth()); + iconState.setXTranslation(getRtlIconTranslationX(iconState, view)); } } if (mIsolatedIcon != null) { @@ -553,6 +552,11 @@ public class NotificationIconContainer extends ViewGroup { } } + /** We need this to keep icons ordered from right to left when RTL. */ + protected float getRtlIconTranslationX(IconState iconState, View iconView) { + return getWidth() - iconState.getXTranslation() - iconView.getWidth(); + } + private float getDrawingScale(View view) { return mUseIncreasedIconScale && view instanceof StatusBarIconView ? ((StatusBarIconView) view).getIconScaleIncreased() @@ -563,11 +567,21 @@ public class NotificationIconContainer extends ViewGroup { mUseIncreasedIconScale = useIncreasedIconScale; } - private float getLayoutEnd() { + /** + * @return The right boundary (not the RTL compatible end) of the area that icons can be added. + */ + protected float getRightBound() { return getActualWidth() - getActualPaddingEnd(); } - private float getActualPaddingEnd() { + /** + * @return The left boundary (not the RTL compatible start) of the area that icons can be added. + */ + protected float getLeftBound() { + return getActualPaddingStart(); + } + + protected float getActualPaddingEnd() { if (mActualPaddingEnd == NO_VALUE) { return getPaddingEnd(); } |