diff options
10 files changed, 117 insertions, 71 deletions
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index e40247ba2d9a..2bf5368b691b 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -4888,12 +4888,6 @@ public class Notification implements Parcelable mN.mUsesStandardHeader = false; } - private RemoteViews applyStandardTemplate(int resId, int viewType, - TemplateBindResult result) { - return applyStandardTemplate(resId, - mParams.reset().viewType(viewType).fillTextsFrom(this), result); - } - private RemoteViews applyStandardTemplate(int resId, StandardTemplateParams p, TemplateBindResult result) { p.headerless(resId == getBaseLayoutResource() @@ -4907,7 +4901,7 @@ public class Notification implements Parcelable bindNotificationHeader(contentView, p); bindLargeIconAndApplyMargin(contentView, p, result); boolean showProgress = handleProgressBar(contentView, ex, p); - if (p.title != null && p.title.length() > 0) { + if (p.title != null && p.title.length() > 0 && !p.mHasCustomContent) { contentView.setViewVisibility(R.id.title, View.VISIBLE); contentView.setTextViewText(R.id.title, processTextSpans(p.title)); setTextViewColorPrimary(contentView, R.id.title, p); @@ -5302,6 +5296,12 @@ public class Notification implements Parcelable contentView.setViewVisibility(R.id.app_name_text, View.GONE); return false; } + if (p.mHeaderless && !p.mHasCustomContent) { + contentView.setViewVisibility(R.id.app_name_text, View.GONE); + // the headerless template will have the TITLE in this position; return true to + // keep the divider visible between that title and the next text element. + return true; + } contentView.setViewVisibility(R.id.app_name_text, View.VISIBLE); contentView.setTextViewText(R.id.app_name_text, loadHeaderAppName()); if (isColorized(p)) { @@ -5356,12 +5356,6 @@ public class Notification implements Parcelable snoozeEnabled ? 0 : R.dimen.notification_content_margin); } - private RemoteViews applyStandardTemplateWithActions(int layoutId, int viewType, - TemplateBindResult result) { - return applyStandardTemplateWithActions(layoutId, - mParams.reset().viewType(viewType).fillTextsFrom(this), result); - } - private static List<Notification.Action> filterOutContextualActions( List<Notification.Action> actions) { List<Notification.Action> nonContextualActions = new ArrayList<>(); @@ -5499,8 +5493,10 @@ public class Notification implements Parcelable return styleView; } } - return applyStandardTemplate(getBaseLayoutResource(), - StandardTemplateParams.VIEW_TYPE_NORMAL, null /* result */); + StandardTemplateParams p = mParams.reset() + .viewType(StandardTemplateParams.VIEW_TYPE_NORMAL) + .fillTextsFrom(this); + return applyStandardTemplate(getBaseLayoutResource(), p, null /* result */); } private boolean useExistingRemoteView() { @@ -5520,14 +5516,27 @@ public class Notification implements Parcelable result = mStyle.makeBigContentView(); hideLine1Text(result); } - if (result == null) { - result = applyStandardTemplateWithActions(getBigBaseLayoutResource(), - StandardTemplateParams.VIEW_TYPE_BIG, null /* result */); + if (result == null && bigContentViewRequired()) { + StandardTemplateParams p = mParams.reset() + .viewType(StandardTemplateParams.VIEW_TYPE_BIG) + .fillTextsFrom(this); + result = applyStandardTemplateWithActions(getBigBaseLayoutResource(), p, + null /* result */); } makeHeaderExpanded(result); return result; } + private boolean bigContentViewRequired() { + // If the big content view has no content, we can exempt the app from having to show it. + // TODO(b/173550917): add an UNDO style then force this requirement on apps targeting S + boolean exempt = mN.contentView != null && mN.bigContentView == null + && mStyle == null && mActions.size() == 0 + && mN.extras.getCharSequence(EXTRA_TITLE) == null + && mN.extras.getCharSequence(EXTRA_TEXT) == null; + return !exempt; + } + /** * Construct a RemoteViews for the final notification header only. This will not be * colorized. @@ -8693,18 +8702,24 @@ public class Notification implements Parcelable return makeStandardTemplateWithCustomContent(headsUpContentView); } TemplateBindResult result = new TemplateBindResult(); + StandardTemplateParams p = mBuilder.mParams.reset() + .viewType(StandardTemplateParams.VIEW_TYPE_HEADS_UP) + .hasCustomContent(headsUpContentView != null) + .fillTextsFrom(mBuilder); RemoteViews remoteViews = mBuilder.applyStandardTemplateWithActions( - mBuilder.getHeadsUpBaseLayoutResource(), - StandardTemplateParams.VIEW_TYPE_HEADS_UP, result); + mBuilder.getHeadsUpBaseLayoutResource(), p, result); buildIntoRemoteViewContent(remoteViews, headsUpContentView, result, true); return remoteViews; } private RemoteViews makeStandardTemplateWithCustomContent(RemoteViews customContent) { TemplateBindResult result = new TemplateBindResult(); + StandardTemplateParams p = mBuilder.mParams.reset() + .viewType(StandardTemplateParams.VIEW_TYPE_NORMAL) + .hasCustomContent(customContent != null) + .fillTextsFrom(mBuilder); RemoteViews remoteViews = mBuilder.applyStandardTemplate( - mBuilder.getBaseLayoutResource(), - StandardTemplateParams.VIEW_TYPE_NORMAL, result); + mBuilder.getBaseLayoutResource(), p, result); buildIntoRemoteViewContent(remoteViews, customContent, result, true); return remoteViews; } @@ -8714,9 +8729,12 @@ public class Notification implements Parcelable ? mBuilder.mN.contentView : mBuilder.mN.bigContentView; TemplateBindResult result = new TemplateBindResult(); + StandardTemplateParams p = mBuilder.mParams.reset() + .viewType(StandardTemplateParams.VIEW_TYPE_BIG) + .hasCustomContent(bigContentView != null) + .fillTextsFrom(mBuilder); RemoteViews remoteViews = mBuilder.applyStandardTemplateWithActions( - mBuilder.getBigBaseLayoutResource(), - StandardTemplateParams.VIEW_TYPE_BIG, result); + mBuilder.getBigBaseLayoutResource(), p, result); buildIntoRemoteViewContent(remoteViews, bigContentView, result, false); return remoteViews; } @@ -11029,6 +11047,7 @@ public class Notification implements Parcelable int mViewType = VIEW_TYPE_UNSPECIFIED; boolean mHeaderless; + boolean mHasCustomContent; boolean hasProgress = true; CharSequence title; CharSequence text; @@ -11042,6 +11061,7 @@ public class Notification implements Parcelable final StandardTemplateParams reset() { mViewType = VIEW_TYPE_UNSPECIFIED; mHeaderless = false; + mHasCustomContent = false; hasProgress = true; title = null; text = null; @@ -11068,6 +11088,11 @@ public class Notification implements Parcelable return this; } + final StandardTemplateParams hasCustomContent(boolean hasCustomContent) { + this.mHasCustomContent = hasCustomContent; + return this; + } + final StandardTemplateParams title(CharSequence title) { this.title = title; return this; diff --git a/core/res/res/layout/notification_material_action_list.xml b/core/res/res/layout/notification_material_action_list.xml index 552a1bd6aa2e..9662b8e35bf6 100644 --- a/core/res/res/layout/notification_material_action_list.xml +++ b/core/res/res/layout/notification_material_action_list.xml @@ -28,7 +28,6 @@ android:layout_height="wrap_content" android:gravity="end" android:orientation="horizontal" - android:paddingEnd="@dimen/bubble_gone_padding_end" android:background="@color/notification_action_list_background_color" > @@ -45,22 +44,34 @@ <!-- actions will be added here --> </com.android.internal.widget.NotificationActionListLayout> - <ImageView - android:id="@+id/snooze_button" - android:layout_width="@dimen/notification_actions_icon_size" - android:layout_height="@dimen/notification_actions_icon_size" - android:layout_gravity="center_vertical|end" - android:visibility="gone" - android:scaleType="centerInside" - /> + <!-- + This nested linear layout exists to ensure that if the neither of the contained + actions is visible we have some minimum padding at the end of the actions is present, + then there will be 12dp of padding at the end of the actions list. + --> + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:orientation="horizontal" + android:minWidth="@dimen/snooze_and_bubble_gone_padding_end" + > + <ImageView + android:id="@+id/snooze_button" + android:layout_width="@dimen/notification_actions_icon_size" + android:layout_height="@dimen/notification_actions_icon_size" + android:layout_gravity="center_vertical|end" + android:visibility="gone" + android:scaleType="centerInside" + /> - <ImageView - android:id="@+id/bubble_button" - android:layout_width="@dimen/notification_actions_icon_size" - android:layout_height="@dimen/notification_actions_icon_size" - android:layout_gravity="center_vertical|end" - android:visibility="gone" - android:scaleType="centerInside" - /> + <ImageView + android:id="@+id/bubble_button" + android:layout_width="@dimen/notification_actions_icon_size" + android:layout_height="@dimen/notification_actions_icon_size" + android:layout_gravity="center_vertical|end" + android:visibility="gone" + android:scaleType="centerInside" + /> + </LinearLayout> </LinearLayout> </FrameLayout> diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml index a26473ad6010..4b67509db457 100644 --- a/core/res/res/layout/notification_template_header.xml +++ b/core/res/res/layout/notification_template_header.xml @@ -50,16 +50,6 @@ android:theme="@style/Theme.DeviceDefault.Notification" > - <TextView - android:id="@+id/app_name_text" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginEnd="@dimen/notification_header_separating_margin" - android:singleLine="true" - android:textAppearance="?attr/notificationHeaderTextAppearance" - android:visibility="?attr/notificationHeaderAppNameVisibility" - /> - <include layout="@layout/notification_top_line_views" /> </NotificationTopLineView> diff --git a/core/res/res/layout/notification_template_material_base.xml b/core/res/res/layout/notification_template_material_base.xml index ded16b7edf87..9d581729df72 100644 --- a/core/res/res/layout/notification_template_material_base.xml +++ b/core/res/res/layout/notification_template_material_base.xml @@ -68,6 +68,12 @@ android:theme="@style/Theme.DeviceDefault.Notification" > + <!-- + NOTE: The notification_top_line_views layout contains the app_name_text. + In order to include the title view at the beginning, the Notification.Builder + has logic to hide that view whenever this title view is to be visible. + --> + <TextView android:id="@+id/title" android:layout_width="wrap_content" diff --git a/core/res/res/layout/notification_template_material_conversation.xml b/core/res/res/layout/notification_template_material_conversation.xml index 520ae282b942..f9364d565f3b 100644 --- a/core/res/res/layout/notification_template_material_conversation.xml +++ b/core/res/res/layout/notification_template_material_conversation.xml @@ -327,10 +327,10 @@ android:id="@+id/expand_button_touch_container" android:layout_width="wrap_content" android:layout_height="@dimen/conversation_expand_button_size" - android:paddingStart="16dp" + android:paddingStart="@dimen/conversation_expand_button_side_margin" android:orientation="horizontal" android:layout_gravity="end|top" - android:paddingEnd="@dimen/notification_content_margin_end" + android:paddingEnd="@dimen/conversation_expand_button_side_margin" android:clipToPadding="false" android:clipChildren="false" > diff --git a/core/res/res/layout/notification_top_line_views.xml b/core/res/res/layout/notification_top_line_views.xml index 51974ac7dcf3..c71e8863502c 100644 --- a/core/res/res/layout/notification_top_line_views.xml +++ b/core/res/res/layout/notification_top_line_views.xml @@ -14,13 +14,23 @@ ~ limitations under the License --> <!-- - This layout file should be included inside a NotificationTopLineView, usually after either a - <TextView android:id="@+id/app_name_text"/> or <TextView android:id="@+id/title"/> + This layout file should be included inside a NotificationTopLineView, sometimes after a + <TextView android:id="@+id/title"/> --> <merge xmlns:android="http://schemas.android.com/apk/res/android"> <TextView + android:id="@+id/app_name_text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="@dimen/notification_header_separating_margin" + android:singleLine="true" + android:textAppearance="?attr/notificationHeaderTextAppearance" + android:visibility="?attr/notificationHeaderAppNameVisibility" + /> + + <TextView android:id="@+id/header_text_secondary_divider" android:layout_width="wrap_content" android:layout_height="wrap_content" diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 79eae67e5fba..38223e6ebdb6 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -340,11 +340,8 @@ <!-- The margin of the content to an image--> <dimen name="notification_content_image_margin_end">8dp</dimen> - <!-- The padding at the end of actions when the bubble button is visible--> - <dimen name="bubble_visible_padding_end">3dp</dimen> - - <!-- The padding at the end of actions when the bubble button is gone--> - <dimen name="bubble_gone_padding_end">12dp</dimen> + <!-- The padding at the end of actions when the snooze and bubble buttons are gone--> + <dimen name="snooze_and_bubble_gone_padding_end">12dp</dimen> <!-- The spacing between messages in Notification.MessagingStyle --> <dimen name="notification_messaging_spacing">6dp</dimen> @@ -744,6 +741,9 @@ <dimen name="conversation_expand_button_size">80dp</dimen> <!-- Top margin of the expand button for conversations when expanded --> <dimen name="conversation_expand_button_top_margin_expanded">18dp</dimen> + <!-- Side margin of the expand button for conversations. + width of expand asset (22) + 2 * this (13) == notification_header_expand_icon_size (48) --> + <dimen name="conversation_expand_button_side_margin">13dp</dimen> <!-- Side margins of the conversation badge in relation to the conversation icon --> <dimen name="conversation_badge_side_margin">36dp</dimen> <!-- size of the notification badge when applied to the conversation icon --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 752bb5b37a30..6e19290d9760 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3560,8 +3560,6 @@ <java-symbol type="id" name="clip_children_tag" /> <java-symbol type="id" name="bubble_button" /> <java-symbol type="id" name="snooze_button" /> - <java-symbol type="dimen" name="bubble_visible_padding_end" /> - <java-symbol type="dimen" name="bubble_gone_padding_end" /> <java-symbol type="dimen" name="text_size_body_2_material" /> <java-symbol type="dimen" name="messaging_avatar_size" /> <java-symbol type="dimen" name="messaging_group_sending_progress_size" /> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java index 216b83f2b4d5..84818eea8a23 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java @@ -41,6 +41,7 @@ import java.util.Objects; 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() { @@ -119,7 +120,7 @@ public class NotificationHeaderUtil { mRow, com.android.internal.R.id.app_name_text, null, - sTextViewComparator, + sAppNameComparator, sAppNameApplicator)); mComparators.add(HeaderProcessor.forTextView(mRow, com.android.internal.R.id.header_text)); @@ -389,4 +390,17 @@ public class NotificationHeaderUtil { super.apply(parent, view, apply, reset); } } + + private static class AppNameComparator extends TextViewComparator { + @Override + public boolean compare(View parent, View child, Object parentData, Object childData) { + if (isEmpty(child)) { + // In headerless notifications the AppName view exists but is usually GONE (and not + // populated). We need to treat this case as equal to the header in order to + // deduplicate the view. + return true; + } + return super.compare(parent, child, parentData, childData); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java index 328774550f24..74e6c003041e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java @@ -1369,16 +1369,8 @@ public class NotificationContentView extends FrameLayout { bubbleButton.setOnClickListener(mContainingNotification.getBubbleClickListener()); bubbleButton.setVisibility(VISIBLE); actionContainer.setVisibility(VISIBLE); - - int paddingEnd = getResources().getDimensionPixelSize( - com.android.internal.R.dimen.bubble_visible_padding_end); - actionContainerLayout.setPaddingRelative(0, 0, paddingEnd, 0); } else { bubbleButton.setVisibility(GONE); - - int paddingEnd = getResources().getDimensionPixelSize( - com.android.internal.R.dimen.bubble_gone_padding_end); - actionContainerLayout.setPaddingRelative(0, 0, paddingEnd, 0); } } |
