summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/Notification.java102
-rw-r--r--core/res/res/layout/notification_template_header.xml12
-rw-r--r--core/res/res/layout/notification_template_material_base.xml14
-rw-r--r--core/res/res/values/dimens.xml4
-rw-r--r--core/res/res/values/ids.xml6
-rw-r--r--core/res/res/values/symbols.xml4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationGroupingUtil.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java)220
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java17
10 files changed, 271 insertions, 124 deletions
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index a886beddf64c..d5572bf130c1 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -30,6 +30,7 @@ import android.annotation.IdRes;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.Px;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
@@ -5105,33 +5106,29 @@ public class Notification implements Parcelable
if (result == null) {
result = new TemplateBindResult();
}
- boolean largeIconShown = bindLargeIcon(contentView, p);
+ final boolean largeIconShown = bindLargeIcon(contentView, p);
calculateLargeIconMarginEnd(largeIconShown, result);
if (p.mHeaderless) {
// views in the headerless (collapsed) state
- contentView.setViewLayoutMarginEnd(R.id.notification_standard_view_column,
- result.getHeadingExtraMarginEnd());
+ result.mHeadingExtraMarginSet.applyToView(contentView,
+ R.id.notification_headerless_view_column);
} else {
// views in states with a header (big states)
- contentView.setInt(R.id.notification_header, "setTopLineExtraMarginEnd",
- result.getHeadingExtraMarginEnd());
- contentView.setViewLayoutMarginEnd(R.id.line1, result.getTitleMarginEnd());
+ result.mHeadingExtraMarginSet.applyToView(contentView, R.id.notification_header);
+ result.mTitleMarginSet.applyToView(contentView, R.id.line1);
}
}
private void calculateLargeIconMarginEnd(boolean largeIconShown,
@NonNull TemplateBindResult result) {
- int contentMargin = mContext.getResources().getDimensionPixelSize(
+ final Resources resources = mContext.getResources();
+ final int contentMargin = resources.getDimensionPixelOffset(
R.dimen.notification_content_margin_end);
- int expanderSize = mContext.getResources().getDimensionPixelSize(
+ final int expanderSize = resources.getDimensionPixelSize(
R.dimen.notification_header_expand_icon_size) - contentMargin;
- int extraMarginEnd = 0;
- if (largeIconShown) {
- int iconSize = mContext.getResources().getDimensionPixelSize(
- R.dimen.notification_right_icon_size);
- extraMarginEnd = iconSize + contentMargin;
- }
- result.setRightIconState(largeIconShown, extraMarginEnd, expanderSize);
+ final int extraMarginEndIfVisible = resources.getDimensionPixelSize(
+ R.dimen.notification_right_icon_size) + contentMargin;
+ result.setRightIconState(largeIconShown, extraMarginEndIfVisible, expanderSize);
}
/**
@@ -7759,8 +7756,10 @@ public class Notification implements Parcelable
addExtras(mBuilder.mN.extras);
if (!isConversationLayout) {
// also update the end margin if there is an image
+ // NOTE: This template doesn't support moving this icon to the left, so we don't
+ // need to fully apply the MarginSet
contentView.setViewLayoutMarginEnd(R.id.notification_messaging,
- bindResult.getHeadingExtraMarginEnd());
+ bindResult.mHeadingExtraMarginSet.getValue());
}
contentView.setInt(R.id.status_bar_latest_event_content, "setLayoutColor",
mBuilder.isColorized(p)
@@ -8757,9 +8756,8 @@ public class Notification implements Parcelable
if (!headerless) {
// also update the end margin to account for the large icon or expander
Resources resources = mBuilder.mContext.getResources();
- int endMargin = resources.getDimensionPixelSize(
- R.dimen.notification_content_margin_end) + result.getTitleMarginEnd();
- remoteViews.setViewLayoutMarginEnd(R.id.notification_main_column, endMargin);
+ result.mTitleMarginSet.applyToView(remoteViews, R.id.notification_main_column,
+ resources.getDimensionPixelOffset(R.dimen.notification_content_margin_end));
}
}
@@ -10997,42 +10995,74 @@ public class Notification implements Parcelable
*/
private static class TemplateBindResult {
boolean mRightIconVisible;
- int mRightIconMarginEnd;
- int mExpanderSize;
/**
- * @return the margin end that needs to be added to the heading so that it won't overlap
+ * The margin end that needs to be added to the heading so that it won't overlap
* with the large icon. This value includes the space required to accommodate the large
* icon, but should be added to the space needed to accommodate the expander. This does
* not include the 16dp content margin that all notification views must have.
*/
- public int getHeadingExtraMarginEnd() {
- return mRightIconMarginEnd;
- }
+ public final MarginSet mHeadingExtraMarginSet = new MarginSet();
/**
- * @return the margin end that needs to be added to the heading so that it won't overlap
+ * The margin end that needs to be added to the heading so that it won't overlap
* with the large icon. This value includes the space required to accommodate the large
* icon as well as the expander. This does not include the 16dp content margin that all
* notification views must have.
*/
- public int getHeadingFullMarginEnd() {
- return mRightIconMarginEnd + mExpanderSize;
- }
+ public final MarginSet mHeadingFullMarginSet = new MarginSet();
/**
- * @return the margin end that needs to be added to the title text of the big state
+ * The margin end that needs to be added to the title text of the big state
* so that it won't overlap with the large icon, but assuming the text can run under
* the expander when that icon is not visible.
*/
- public int getTitleMarginEnd() {
- return mRightIconVisible ? getHeadingFullMarginEnd() : 0;
- }
+ public final MarginSet mTitleMarginSet = new MarginSet();
- public void setRightIconState(boolean visible, int marginEnd, int expanderSize) {
+ public void setRightIconState(boolean visible, int marginEndIfVisible, int expanderSize) {
mRightIconVisible = visible;
- mRightIconMarginEnd = marginEnd;
- mExpanderSize = expanderSize;
+ mHeadingExtraMarginSet.setValues(0, marginEndIfVisible);
+ mHeadingFullMarginSet.setValues(expanderSize, marginEndIfVisible + expanderSize);
+ mTitleMarginSet.setValues(0, marginEndIfVisible + expanderSize);
+ }
+
+ /**
+ * This contains the end margins for a view when the right icon is visible or not. These
+ * values are both needed so that NotificationGroupingUtil can 'move' the right_icon to the
+ * left_icon and adjust the margins, and to undo that change as well.
+ */
+ private class MarginSet {
+ private int mValueIfGone;
+ private int mValueIfVisible;
+
+ public void setValues(int valueIfGone, int valueIfVisible) {
+ mValueIfGone = valueIfGone;
+ mValueIfVisible = valueIfVisible;
+ }
+
+ public void applyToView(@NonNull RemoteViews views, @IdRes int viewId) {
+ applyToView(views, viewId, 0);
+ }
+
+ public void applyToView(@NonNull RemoteViews views, @IdRes int viewId,
+ @Px int extraMargin) {
+ final int marginEnd = getValue() + extraMargin;
+ if (viewId == R.id.notification_header) {
+ views.setInt(R.id.notification_header, "setTopLineExtraMarginEnd", marginEnd);
+ } else {
+ views.setViewLayoutMarginEnd(viewId, marginEnd);
+ }
+ if (mRightIconVisible) {
+ views.setIntTag(viewId, R.id.tag_margin_end_when_icon_visible,
+ mValueIfVisible + extraMargin);
+ views.setIntTag(viewId, R.id.tag_margin_end_when_icon_gone,
+ mValueIfGone + extraMargin);
+ }
+ }
+
+ public int getValue() {
+ return mRightIconVisible ? mValueIfVisible : mValueIfGone;
+ }
}
}
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index b0ee12a520d9..88998f2167a8 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -26,6 +26,18 @@
android:theme="@style/Theme.DeviceDefault.Notification"
>
+ <ImageView
+ android:id="@+id/left_icon"
+ android:layout_width="@dimen/notification_left_icon_size"
+ android:layout_height="@dimen/notification_left_icon_size"
+ android:layout_gravity="center_vertical|start"
+ android:layout_marginStart="@dimen/notification_left_icon_start"
+ android:background="@drawable/notification_large_icon_outline"
+ android:importantForAccessibility="no"
+ android:scaleType="centerCrop"
+ android:visibility="gone"
+ />
+
<com.android.internal.widget.CachingIconView
android:id="@+id/icon"
android:layout_width="@dimen/notification_icon_circle_size"
diff --git a/core/res/res/layout/notification_template_material_base.xml b/core/res/res/layout/notification_template_material_base.xml
index 69d4a12f4d69..000638475a10 100644
--- a/core/res/res/layout/notification_template_material_base.xml
+++ b/core/res/res/layout/notification_template_material_base.xml
@@ -23,6 +23,18 @@
android:tag="base"
>
+ <ImageView
+ android:id="@+id/left_icon"
+ android:layout_width="@dimen/notification_left_icon_size"
+ android:layout_height="@dimen/notification_left_icon_size"
+ android:layout_gravity="center_vertical|start"
+ android:layout_marginStart="@dimen/notification_left_icon_start"
+ android:background="@drawable/notification_large_icon_outline"
+ android:importantForAccessibility="no"
+ android:scaleType="centerCrop"
+ android:visibility="gone"
+ />
+
<com.android.internal.widget.CachingIconView
android:id="@+id/icon"
android:layout_width="@dimen/notification_icon_circle_size"
@@ -34,7 +46,7 @@
/>
<LinearLayout
- android:id="@+id/notification_standard_view_column"
+ android:id="@+id/notification_headerless_view_column"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 19591f6a666f..4bcabff109ea 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -714,6 +714,10 @@
<dimen name="notification_right_icon_headerless_margin">12dp</dimen>
<!-- The top margin of the right icon in the "big" notification states -->
<dimen name="notification_right_icon_big_margin_top">16dp</dimen>
+ <!-- The size of the left icon -->
+ <dimen name="notification_left_icon_size">@dimen/notification_icon_circle_size</dimen>
+ <!-- The left padding of the left icon -->
+ <dimen name="notification_left_icon_start">@dimen/notification_icon_circle_start</dimen>
<!-- The alpha of a disabled notification button -->
<item type="dimen" format="float" name="notification_action_disabled_alpha">0.5</item>
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index f77c6f99c063..a12d2a951460 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -194,6 +194,12 @@
<!-- A tag used to save the index where the custom view is stored -->
<item type="id" name="notification_custom_view_index_tag" />
+ <!-- A tag used to store the margin end for this view when the right icon is visible -->
+ <item type="id" name="tag_margin_end_when_icon_gone" />
+
+ <!-- A tag used to store the margin end for this view when the right icon is gone -->
+ <item type="id" name="tag_margin_end_when_icon_visible" />
+
<!-- Marks the "copy to clipboard" button in the ChooserActivity -->
<item type="id" name="chooser_copy_button" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e3986fa96fb5..6da7eba62585 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -218,7 +218,7 @@
<java-symbol type="id" name="inbox_text6" />
<java-symbol type="id" name="status_bar_latest_event_content" />
<java-symbol type="id" name="notification_main_column" />
- <java-symbol type="id" name="notification_standard_view_column" />
+ <java-symbol type="id" name="notification_headerless_view_column" />
<java-symbol type="id" name="sms_short_code_confirm_message" />
<java-symbol type="id" name="sms_short_code_detail_layout" />
<java-symbol type="id" name="sms_short_code_detail_message" />
@@ -3070,6 +3070,8 @@
<java-symbol type="dimen" name="notification_media_image_margin_end" />
<java-symbol type="id" name="notification_action_list_margin_target" />
<java-symbol type="dimen" name="notification_action_disabled_alpha" />
+ <java-symbol type="id" name="tag_margin_end_when_icon_visible" />
+ <java-symbol type="id" name="tag_margin_end_when_icon_gone" />
<!-- Override Wake Key Behavior When Screen is Off -->
<java-symbol type="bool" name="config_wakeOnDpadKeyPress" />
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGroupingUtil.java
index 84818eea8a23..0e6bcc58b7c0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGroupingUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -11,19 +11,22 @@
* 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
+ * limitations under the License.
*/
package com.android.systemui.statusbar;
import android.app.Notification;
+import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.text.TextUtils;
+import android.view.NotificationHeaderView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
+import com.android.internal.R;
import com.android.internal.widget.CachingIconView;
import com.android.internal.widget.ConversationLayout;
import com.android.internal.widget.NotificationExpandButton;
@@ -36,35 +39,38 @@ import java.util.List;
import java.util.Objects;
/**
- * A Util to manage {@link android.view.NotificationHeaderView} objects and their redundancies.
+ * A utility to manage notification views when they are placed in a group by adjusting elements
+ * to reduce redundancies and occasionally tweak layouts to highlight the unique content.
*/
-public class NotificationHeaderUtil {
-
- private static final TextViewComparator sTextViewComparator = new TextViewComparator();
- private static final TextViewComparator sAppNameComparator = new AppNameComparator();
- private static final VisibilityApplicator sVisibilityApplicator = new VisibilityApplicator();
- private static final VisibilityApplicator sAppNameApplicator = new AppNameApplicator();
- private static final DataExtractor sIconExtractor = new DataExtractor() {
+public class NotificationGroupingUtil {
+
+ private static final TextViewComparator TEXT_VIEW_COMPARATOR = new TextViewComparator();
+ private static final TextViewComparator APP_NAME_COMPARATOR = new AppNameComparator();
+ private static final ViewComparator BADGE_COMPARATOR = new BadgeComparator();
+ private static final VisibilityApplicator VISIBILITY_APPLICATOR = new VisibilityApplicator();
+ private static final VisibilityApplicator APP_NAME_APPLICATOR = new AppNameApplicator();
+ private static final ResultApplicator LEFT_ICON_APPLICATOR = new LeftIconApplicator();
+ private static final DataExtractor ICON_EXTRACTOR = new DataExtractor() {
@Override
public Object extractData(ExpandableNotificationRow row) {
return row.getEntry().getSbn().getNotification();
}
};
- private static final IconComparator sIconVisibilityComparator = new IconComparator() {
+ private static final IconComparator ICON_VISIBILITY_COMPARATOR = new IconComparator() {
public boolean compare(View parent, View child, Object parentData,
Object childData) {
return hasSameIcon(parentData, childData)
&& hasSameColor(parentData, childData);
}
};
- private static final IconComparator sGreyComparator = new IconComparator() {
+ private static final IconComparator GREY_COMPARATOR = new IconComparator() {
public boolean compare(View parent, View child, Object parentData,
Object childData) {
return !hasSameIcon(parentData, childData)
|| hasSameColor(parentData, childData);
}
};
- private final static ResultApplicator mGreyApplicator = new ResultApplicator() {
+ private static final ResultApplicator GREY_APPLICATOR = new ResultApplicator() {
@Override
public void apply(View parent, View view, boolean apply, boolean reset) {
CachingIconView icon = view.findViewById(com.android.internal.R.id.icon);
@@ -80,87 +86,79 @@ public class NotificationHeaderUtil {
};
private final ExpandableNotificationRow mRow;
- private final ArrayList<HeaderProcessor> mComparators = new ArrayList<>();
+ private final ArrayList<Processor> mProcessors = new ArrayList<>();
private final HashSet<Integer> mDividers = new HashSet<>();
- public NotificationHeaderUtil(ExpandableNotificationRow row) {
+ public NotificationGroupingUtil(ExpandableNotificationRow row) {
mRow = row;
// To hide the icons if they are the same and the color is the same
- mComparators.add(new HeaderProcessor(mRow,
+ mProcessors.add(new Processor(mRow,
com.android.internal.R.id.icon,
- sIconExtractor,
- sIconVisibilityComparator,
- sVisibilityApplicator));
+ ICON_EXTRACTOR,
+ ICON_VISIBILITY_COMPARATOR,
+ VISIBILITY_APPLICATOR));
// To grey them out the icons and expand button when the icons are not the same
- mComparators.add(new HeaderProcessor(mRow,
- com.android.internal.R.id.notification_header,
- sIconExtractor,
- sGreyComparator,
- mGreyApplicator));
- mComparators.add(new HeaderProcessor(mRow,
+ mProcessors.add(new Processor(mRow,
+ com.android.internal.R.id.status_bar_latest_event_content,
+ ICON_EXTRACTOR,
+ GREY_COMPARATOR,
+ GREY_APPLICATOR));
+ mProcessors.add(new Processor(mRow,
+ com.android.internal.R.id.status_bar_latest_event_content,
+ ICON_EXTRACTOR,
+ ICON_VISIBILITY_COMPARATOR,
+ LEFT_ICON_APPLICATOR));
+ mProcessors.add(new Processor(mRow,
com.android.internal.R.id.profile_badge,
null /* Extractor */,
- new ViewComparator() {
- @Override
- public boolean compare(View parent, View child, Object parentData,
- Object childData) {
- return parent.getVisibility() != View.GONE;
- }
-
- @Override
- public boolean isEmpty(View view) {
- if (view instanceof ImageView) {
- return ((ImageView) view).getDrawable() == null;
- }
- return false;
- }
- },
- sVisibilityApplicator));
- mComparators.add(new HeaderProcessor(
- mRow,
+ BADGE_COMPARATOR,
+ VISIBILITY_APPLICATOR));
+ mProcessors.add(new Processor(mRow,
com.android.internal.R.id.app_name_text,
null,
- sAppNameComparator,
- sAppNameApplicator));
- mComparators.add(HeaderProcessor.forTextView(mRow,
- com.android.internal.R.id.header_text));
+ APP_NAME_COMPARATOR,
+ APP_NAME_APPLICATOR));
+ mProcessors.add(Processor.forTextView(mRow, com.android.internal.R.id.header_text));
mDividers.add(com.android.internal.R.id.header_text_divider);
mDividers.add(com.android.internal.R.id.header_text_secondary_divider);
mDividers.add(com.android.internal.R.id.time_divider);
}
- public void updateChildrenHeaderAppearance() {
+ /**
+ * Update the appearance of the children in this group to reduce redundancies.
+ */
+ public void updateChildrenAppearance() {
List<ExpandableNotificationRow> notificationChildren = mRow.getAttachedChildren();
if (notificationChildren == null) {
return;
}
- // Initialize the comparators
- for (int compI = 0; compI < mComparators.size(); compI++) {
- mComparators.get(compI).init();
+ // Initialize the processors
+ for (int compI = 0; compI < mProcessors.size(); compI++) {
+ mProcessors.get(compI).init();
}
// Compare all notification headers
for (int i = 0; i < notificationChildren.size(); i++) {
ExpandableNotificationRow row = notificationChildren.get(i);
- for (int compI = 0; compI < mComparators.size(); compI++) {
- mComparators.get(compI).compareToHeader(row);
+ for (int compI = 0; compI < mProcessors.size(); compI++) {
+ mProcessors.get(compI).compareToGroupParent(row);
}
}
// Apply the comparison to the row
for (int i = 0; i < notificationChildren.size(); i++) {
ExpandableNotificationRow row = notificationChildren.get(i);
- for (int compI = 0; compI < mComparators.size(); compI++) {
- mComparators.get(compI).apply(row);
+ for (int compI = 0; compI < mProcessors.size(); compI++) {
+ mProcessors.get(compI).apply(row);
}
// We need to sanitize the dividers since they might be off-balance now
- sanitizeHeaderViews(row);
+ sanitizeTopLineViews(row);
}
}
- private void sanitizeHeaderViews(ExpandableNotificationRow row) {
+ private void sanitizeTopLineViews(ExpandableNotificationRow row) {
if (row.isSummaryWithChildren()) {
- sanitizeHeader(row.getNotificationViewWrapper().getNotificationHeader());
+ sanitizeTopLine(row.getNotificationViewWrapper().getNotificationHeader());
return;
}
final NotificationContentView layout = row.getPrivateLayout();
@@ -171,13 +169,11 @@ public class NotificationHeaderUtil {
private void sanitizeChild(View child) {
if (child != null) {
- ViewGroup header = child.findViewById(
- com.android.internal.R.id.notification_top_line);
- sanitizeHeader(header);
+ sanitizeTopLine(child.findViewById(R.id.notification_top_line));
}
}
- private void sanitizeHeader(ViewGroup rowHeader) {
+ private void sanitizeTopLine(ViewGroup rowHeader) {
if (rowHeader == null) {
return;
}
@@ -225,28 +221,31 @@ public class NotificationHeaderUtil {
}
}
- public void restoreNotificationHeader(ExpandableNotificationRow row) {
- for (int compI = 0; compI < mComparators.size(); compI++) {
- mComparators.get(compI).apply(row, true /* reset */);
+ /**
+ * Reset the modifications to this row for removing it from the group.
+ */
+ public void restoreChildNotification(ExpandableNotificationRow row) {
+ for (int compI = 0; compI < mProcessors.size(); compI++) {
+ mProcessors.get(compI).apply(row, true /* reset */);
}
- sanitizeHeaderViews(row);
+ sanitizeTopLineViews(row);
}
- private static class HeaderProcessor {
+ private static class Processor {
private final int mId;
private final DataExtractor mExtractor;
+ private final ViewComparator mComparator;
private final ResultApplicator mApplicator;
private final ExpandableNotificationRow mParentRow;
private boolean mApply;
private View mParentView;
- private ViewComparator mComparator;
private Object mParentData;
- public static HeaderProcessor forTextView(ExpandableNotificationRow row, int id) {
- return new HeaderProcessor(row, id, null, sTextViewComparator, sVisibilityApplicator);
+ public static Processor forTextView(ExpandableNotificationRow row, int id) {
+ return new Processor(row, id, null, TEXT_VIEW_COMPARATOR, VISIBILITY_APPLICATOR);
}
- HeaderProcessor(ExpandableNotificationRow row, int id, DataExtractor extractor,
+ Processor(ExpandableNotificationRow row, int id, DataExtractor extractor,
ViewComparator comparator,
ResultApplicator applicator) {
mId = id;
@@ -262,7 +261,7 @@ public class NotificationHeaderUtil {
mParentData = mExtractor == null ? null : mExtractor.extractData(mParentRow);
mApply = !mComparator.isEmpty(mParentView);
}
- public void compareToHeader(ExpandableNotificationRow row) {
+ public void compareToGroupParent(ExpandableNotificationRow row) {
if (!mApply) {
return;
}
@@ -308,8 +307,8 @@ public class NotificationHeaderUtil {
private interface ViewComparator {
/**
- * @param parent the parent view
- * @param child the child view
+ * @param parent the view with the given id in the group header
+ * @param child the view with the given id in the child notification
* @param parentData optional data for the parent
* @param childData optional data for the child
* @return whether to views are the same
@@ -322,6 +321,21 @@ public class NotificationHeaderUtil {
Object extractData(ExpandableNotificationRow row);
}
+ private static class BadgeComparator implements ViewComparator {
+ @Override
+ public boolean compare(View parent, View child, Object parentData, Object childData) {
+ return parent.getVisibility() != View.GONE;
+ }
+
+ @Override
+ public boolean isEmpty(View view) {
+ if (view instanceof ImageView) {
+ return ((ImageView) view).getDrawable() == null;
+ }
+ return false;
+ }
+ }
+
private static class TextViewComparator implements ViewComparator {
@Override
public boolean compare(View parent, View child, Object parentData, Object childData) {
@@ -338,7 +352,7 @@ public class NotificationHeaderUtil {
}
}
- private static abstract class IconComparator implements ViewComparator {
+ private abstract static class IconComparator implements ViewComparator {
@Override
public boolean compare(View parent, View child, Object parentData, Object childData) {
return false;
@@ -366,6 +380,12 @@ public class NotificationHeaderUtil {
}
private interface ResultApplicator {
+ /**
+ * @param parent the root view of the child notification
+ * @param view the view with the given id in the child notification
+ * @param apply whether the state should be applied or removed
+ * @param reset if [de]application is the result of a reset
+ */
void apply(View parent, View view, boolean apply, boolean reset);
}
@@ -403,4 +423,54 @@ public class NotificationHeaderUtil {
return super.compare(parent, child, parentData, childData);
}
}
+
+ private static class LeftIconApplicator implements ResultApplicator {
+
+ public static final int[] MARGIN_ADJUSTED_VIEWS = {
+ R.id.notification_headerless_view_column,
+ R.id.line1,
+ R.id.notification_main_column,
+ R.id.notification_header};
+
+ @Override
+ public void apply(View parent, View child, boolean apply, boolean reset) {
+ ImageView rightIcon = child.findViewById(com.android.internal.R.id.right_icon);
+ ImageView leftIcon = child.findViewById(com.android.internal.R.id.left_icon);
+ if (rightIcon == null || leftIcon == null) {
+ return;
+ }
+ Drawable iconDrawable = rightIcon.getDrawable();
+ if (iconDrawable == null) {
+ return;
+ }
+ rightIcon.setVisibility(apply ? View.GONE : View.VISIBLE);
+ leftIcon.setVisibility(apply ? View.VISIBLE : View.GONE);
+ leftIcon.setImageDrawable(apply ? iconDrawable : null);
+
+ for (int viewId : MARGIN_ADJUSTED_VIEWS) {
+ adjustMargins(!apply, child.findViewById(viewId));
+ }
+ }
+
+ void adjustMargins(boolean iconVisible, View target) {
+ if (target == null) {
+ return;
+ }
+ Integer value = (Integer) target.getTag(iconVisible
+ ? com.android.internal.R.id.tag_margin_end_when_icon_visible
+ : com.android.internal.R.id.tag_margin_end_when_icon_gone);
+ if (value == null) {
+ return;
+ }
+ if (target instanceof NotificationHeaderView) {
+ ((NotificationHeaderView) target).setTopLineExtraMarginEnd(value);
+ } else {
+ ViewGroup.LayoutParams layoutParams = target.getLayoutParams();
+ if (layoutParams instanceof ViewGroup.MarginLayoutParams) {
+ ((ViewGroup.MarginLayoutParams) layoutParams).setMarginEnd(value);
+ target.setLayoutParams(layoutParams);
+ }
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 5ed17f1ee07f..10118e4733ba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -558,7 +558,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
setChronometerRunning(true);
}
if (mNotificationParent != null) {
- mNotificationParent.updateChildrenHeaderAppearance();
+ mNotificationParent.updateChildrenAppearance();
}
onAttachedChildrenCountChanged();
// The public layouts expand button is always visible
@@ -2337,7 +2337,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
getShowingLayout().updateBackgroundColor(false /* animate */);
mPrivateLayout.updateExpandButtons(isExpandable());
- updateChildrenHeaderAppearance();
+ updateChildrenAppearance();
updateChildrenVisibility();
applyChildrenRoundness();
}
@@ -2382,9 +2382,12 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
return channels;
}
- public void updateChildrenHeaderAppearance() {
+ /**
+ * If this is a group, update the appearance of the children.
+ */
+ public void updateChildrenAppearance() {
if (mIsSummaryWithChildren) {
- mChildrenContainer.updateChildrenHeaderAppearance();
+ mChildrenContainer.updateChildrenAppearance();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
index 05db67d706cf..37d5da24a704 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
@@ -64,6 +64,7 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
private ImageView mWorkProfileImage;
private View mAudiblyAlertedIcon;
private View mFeedbackIcon;
+ private View mLeftIcon;
private View mRightIcon;
private boolean mIsLowPriority;
@@ -108,6 +109,7 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
mAppNameText = mView.findViewById(com.android.internal.R.id.app_name_text);
mExpandButton = mView.findViewById(com.android.internal.R.id.expand_button);
mAltExpandTarget = mView.findViewById(com.android.internal.R.id.alternate_expand_target);
+ mLeftIcon = mView.findViewById(com.android.internal.R.id.left_icon);
mRightIcon = mView.findViewById(com.android.internal.R.id.right_icon);
mWorkProfileImage = mView.findViewById(com.android.internal.R.id.profile_badge);
mNotificationHeader = mView.findViewById(com.android.internal.R.id.notification_header);
@@ -146,6 +148,9 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
updateCropToPaddingForImageViews();
Notification notification = row.getEntry().getSbn().getNotification();
mIcon.setTag(ImageTransformState.ICON_TAG, notification.getSmallIcon());
+ if (mLeftIcon != null) {
+ mLeftIcon.setClipToOutline(true);
+ }
if (mRightIcon != null) {
mRightIcon.setClipToOutline(true);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index b04f94ce9c1d..601fc197cfa6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -34,7 +34,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.widget.CachingIconView;
import com.android.systemui.R;
import com.android.systemui.statusbar.CrossFadeHelper;
-import com.android.systemui.statusbar.NotificationHeaderUtil;
+import com.android.systemui.statusbar.NotificationGroupingUtil;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -94,7 +94,7 @@ public class NotificationChildrenContainer extends ViewGroup {
private NotificationViewWrapper mNotificationHeaderWrapper;
private NotificationHeaderView mNotificationHeaderLowPriority;
private NotificationViewWrapper mNotificationHeaderWrapperLowPriority;
- private NotificationHeaderUtil mHeaderUtil;
+ private NotificationGroupingUtil mGroupingUtil;
private ViewState mHeaderViewState;
private int mClipBottomAmount;
private boolean mIsLowPriority;
@@ -299,7 +299,7 @@ public class NotificationChildrenContainer extends ViewGroup {
row.setSystemChildExpanded(false);
row.setUserLocked(false);
if (!row.isRemoved()) {
- mHeaderUtil.restoreNotificationHeader(row);
+ mGroupingUtil.restoreChildNotification(row);
}
}
@@ -341,7 +341,7 @@ public class NotificationChildrenContainer extends ViewGroup {
}
recreateLowPriorityHeader(builder, isConversation);
updateHeaderVisibility(false /* animate */);
- updateChildrenHeaderAppearance();
+ updateChildrenAppearance();
}
/**
@@ -389,8 +389,11 @@ public class NotificationChildrenContainer extends ViewGroup {
}
}
- public void updateChildrenHeaderAppearance() {
- mHeaderUtil.updateChildrenHeaderAppearance();
+ /**
+ * Update the appearance of the children to reduce redundancies.
+ */
+ public void updateChildrenAppearance() {
+ mGroupingUtil.updateChildrenAppearance();
}
public void updateGroupOverflow() {
@@ -861,7 +864,7 @@ public class NotificationChildrenContainer extends ViewGroup {
public void setContainingNotification(ExpandableNotificationRow parent) {
mContainingNotification = parent;
- mHeaderUtil = new NotificationHeaderUtil(mContainingNotification);
+ mGroupingUtil = new NotificationGroupingUtil(mContainingNotification);
}
public ExpandableNotificationRow getContainingNotification() {