summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Yining Liu <liuyining@google.com> 2024-12-12 19:26:26 +0000
committer Yining Liu <liuyining@google.com> 2024-12-19 21:32:20 +0000
commit4f11fba0da840ff0abf6d43f1840df8c0153ac60 (patch)
tree1039cdd3ba4fbf9c10cb6a7e1398917e22feb996
parent222084ca4fec4e8efb5248e657697b800cf153eb (diff)
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
-rw-r--r--packages/SystemUI/res/layout/status_bar_notification_shelf.xml4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java78
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/NotificationShelfBackgroundView.kt44
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/NotificationShelfIconContainer.kt90
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java30
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();
}