diff options
| -rw-r--r-- | core/java/android/app/Notification.java | 44 | ||||
| -rw-r--r-- | core/java/com/android/internal/widget/NotificationVanishingFrameLayout.java | 70 | ||||
| -rw-r--r-- | core/res/res/layout/notification_template_material_base.xml | 50 | ||||
| -rw-r--r-- | core/res/res/values/dimens.xml | 25 | ||||
| -rw-r--r-- | core/res/res/values/symbols.xml | 6 |
5 files changed, 121 insertions, 74 deletions
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index f8c9a9ecf4c8..7222e8650a08 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -5013,6 +5013,7 @@ public class Notification implements Parcelable bindNotificationHeader(contentView, p); bindLargeIconAndApplyMargin(contentView, p, result); boolean showProgress = handleProgressBar(contentView, ex, p); + boolean hasSecondLine = showProgress; if (p.hasTitle()) { contentView.setViewVisibility(R.id.title, View.VISIBLE); contentView.setTextViewText(R.id.title, processTextSpans(p.title)); @@ -5028,11 +5029,27 @@ public class Notification implements Parcelable contentView.setTextViewText(textId, processTextSpans(p.text)); setTextViewColorSecondary(contentView, textId, p); contentView.setViewVisibility(textId, View.VISIBLE); + hasSecondLine = true; } + setHeaderlessVerticalMargins(contentView, p, hasSecondLine); return contentView; } + private static void setHeaderlessVerticalMargins(RemoteViews contentView, + StandardTemplateParams p, boolean hasSecondLine) { + if (!p.mHeaderless) { + return; + } + int marginDimen = hasSecondLine + ? R.dimen.notification_headerless_margin_twoline + : R.dimen.notification_headerless_margin_oneline; + contentView.setViewLayoutMarginDimen(R.id.notification_headerless_view_column, + RemoteViews.MARGIN_TOP, marginDimen); + contentView.setViewLayoutMarginDimen(R.id.notification_headerless_view_column, + RemoteViews.MARGIN_BOTTOM, marginDimen); + } + private CharSequence processTextSpans(CharSequence text) { if (hasForegroundColor() || mInNightMode) { return ContrastColorUtil.clearColorSpans(text); @@ -6851,26 +6868,13 @@ public class Notification implements Parcelable if (decorationType <= DevFlags.DECORATION_PARTIAL) { template.removeFromParent(R.id.notification_top_line); } - if (decorationType != DevFlags.DECORATION_FULL_COMPATIBLE) { - // Change the max content size from 60dp (the compatible size) to 48dp - // (the constrained size). This is done by increasing the minimum margin - // (implemented as top/bottom margins) and decreasing the extra margin - // (implemented as the height of shrinkable top/bottom views in the column). - template.setViewLayoutMarginDimen( - R.id.notification_headerless_view_column, - RemoteViews.MARGIN_TOP, - R.dimen.notification_headerless_margin_constrained_minimum); - template.setViewLayoutMarginDimen( - R.id.notification_headerless_view_column, - RemoteViews.MARGIN_BOTTOM, - R.dimen.notification_headerless_margin_constrained_minimum); - template.setViewLayoutHeightDimen( - R.id.notification_headerless_margin_extra_top, - R.dimen.notification_headerless_margin_constrained_extra); - template.setViewLayoutHeightDimen( - R.id.notification_headerless_margin_extra_bottom, - R.dimen.notification_headerless_margin_constrained_extra); - } + // The vertical margins are bigger in the "two-line" scenario than the "one-line" + // scenario, but the 'compatible' decoration state is intended to have 3 lines, + // (1 for the top line views and 2 for the custom views), so in that one case we + // use the smaller 1-line margins. This gives the compatible case 88-16*2=56 dp of + // height, 24dp of which goes to the top line, leaving 32dp for the custom view. + boolean hasSecondLine = decorationType != DevFlags.DECORATION_FULL_COMPATIBLE; + Builder.setHeaderlessVerticalMargins(template, p, hasSecondLine); } else { // also update the end margin to account for the large icon or expander Resources resources = context.getResources(); diff --git a/core/java/com/android/internal/widget/NotificationVanishingFrameLayout.java b/core/java/com/android/internal/widget/NotificationVanishingFrameLayout.java new file mode 100644 index 000000000000..742bdfdde756 --- /dev/null +++ b/core/java/com/android/internal/widget/NotificationVanishingFrameLayout.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2021 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.internal.widget; + +import android.annotation.Nullable; +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.RemoteViews; + +/** + * This view will measure itself as having 0 size if all of its children are {@link #GONE}. + * Otherwise it acts like a normal {@link FrameLayout}. + */ +@RemoteViews.RemoteView +public class NotificationVanishingFrameLayout extends FrameLayout { + public NotificationVanishingFrameLayout(Context context) { + this(context, null, 0, 0); + } + + public NotificationVanishingFrameLayout(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0, 0); + } + + public NotificationVanishingFrameLayout(Context context, @Nullable AttributeSet attrs, + int defStyleAttr) { + this(context, attrs, defStyleAttr, 0); + } + + public NotificationVanishingFrameLayout(Context context, AttributeSet attrs, int defStyleAttr, + int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (allChildrenGone()) { + int zeroSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.EXACTLY); + super.onMeasure(zeroSpec, zeroSpec); + } else { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + } + + private boolean allChildrenGone() { + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + if (child != null && child.getVisibility() != GONE) { + return false; + } + } + return true; + } +} diff --git a/core/res/res/layout/notification_template_material_base.xml b/core/res/res/layout/notification_template_material_base.xml index d79cb74a3d53..b83611bcc177 100644 --- a/core/res/res/layout/notification_template_material_base.xml +++ b/core/res/res/layout/notification_template_material_base.xml @@ -91,26 +91,11 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" - android:layout_marginBottom="@dimen/notification_headerless_margin_minimum" - android:layout_marginTop="@dimen/notification_headerless_margin_minimum" + android:layout_marginBottom="@dimen/notification_headerless_margin_twoline" + android:layout_marginTop="@dimen/notification_headerless_margin_twoline" android:orientation="vertical" > - <!-- - This invisible FrameLayout is here as a collapsible padding. Having a layout_weight=1 is - what causes this view (and it's counterpart at the opposite end) to collapse before the - actual content views do. - This pair of 10dp collapsible paddings (plus the 16dp fixed margins) allow us to support - headerless notifications of 1-3 lines (where each line is 20dp tall) where the 1-line - variant is 56dp and the 2- and 3-line variants are both 76dp. - --> - <FrameLayout - android:id="@+id/notification_headerless_margin_extra_top" - android:layout_width="match_parent" - android:layout_height="@dimen/notification_headerless_margin_extra" - android:layout_weight="1" - /> - <!-- extends ViewGroup --> <NotificationTopLineView android:id="@+id/notification_top_line" @@ -153,12 +138,20 @@ android:orientation="vertical" > - <include - layout="@layout/notification_template_text" + <com.android.internal.widget.NotificationVanishingFrameLayout android:layout_width="match_parent" android:layout_height="@dimen/notification_headerless_line_height" - android:layout_marginTop="0dp" - /> + > + <!-- This is the simplest way to keep this text vertically centered without using + gravity="center_vertical" which causes jumpiness in expansion animations. --> + <include + layout="@layout/notification_template_text" + android:layout_width="match_parent" + android:layout_height="@dimen/notification_text_height" + android:layout_gravity="center_vertical" + android:layout_marginTop="0dp" + /> + </com.android.internal.widget.NotificationVanishingFrameLayout> <include layout="@layout/notification_template_progress" @@ -168,21 +161,6 @@ </LinearLayout> - <!-- - This invisible FrameLayout is here as a collapsible padding. Having a layout_weight=1 is - what causes this view (and it's counterpart at the opposite end) to collapse before the - actual content views do. - This pair of 10dp collapsible paddings (plus the 16dp fixed margins) allow us to support - headerless notifications of 1-3 lines (where each line is 20dp tall) where the 1-line - variant is 56dp and the 2- and 3-line variants are both 76dp. - --> - <FrameLayout - android:id="@+id/notification_headerless_margin_extra_bottom" - android:layout_width="match_parent" - android:layout_height="@dimen/notification_headerless_margin_extra" - android:layout_weight="1" - /> - </LinearLayout> </com.android.internal.widget.NotificationMaxHeightFrameLayout> diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 695a831faf97..c2b6b99dcc1c 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -319,26 +319,22 @@ <!-- The top padding for the notification expand button. --> <dimen name="notification_expand_button_padding_top">1dp</dimen> - <!-- minimum vertical margin for the headerless notification content, when cap = 60dp --> - <dimen name="notification_headerless_margin_minimum">8dp</dimen> + <!-- Vertical margin for the headerless notification content, when content has 1 line --> + <!-- 16 * 2 (margins) + 24 (1 line) = 56 (notification) --> + <dimen name="notification_headerless_margin_oneline">16dp</dimen> - <!-- extra vertical margin for the headerless notification content, when cap = 60dp --> - <dimen name="notification_headerless_margin_extra">10dp</dimen> - - <!-- minimum vertical margin for the headerless notification content, when cap = 48dp --> - <dimen name="notification_headerless_margin_constrained_minimum">14dp</dimen> - - <!-- extra vertical margin for the headerless notification content, when cap = 48dp --> - <dimen name="notification_headerless_margin_constrained_extra">4dp</dimen> + <!-- Vertical margin for the headerless notification content, when content has 2 lines --> + <!-- 20 * 2 (margins) + 24 * 2 (2 lines) = 88 (notification) --> + <dimen name="notification_headerless_margin_twoline">20dp</dimen> <!-- The height of each of the 1 or 2 lines in the headerless notification template --> - <dimen name="notification_headerless_line_height">20sp</dimen> + <dimen name="notification_headerless_line_height">24dp</dimen> <!-- vertical margin for the headerless notification content --> <dimen name="notification_headerless_min_height">56dp</dimen> <!-- Height of a small notification in the status bar --> - <dimen name="notification_min_height">76dp</dimen> + <dimen name="notification_min_height">88dp</dimen> <!-- The width of the big icons in notifications. --> <dimen name="notification_large_icon_width">64dp</dimen> @@ -738,10 +734,11 @@ <!-- The maximum width of a image in a media notification. The images will be reduced to that width in case they are bigger.--> <dimen name="notification_media_image_max_width">280dp</dimen> <!-- The size of the right icon --> - <dimen name="notification_right_icon_size">52dp</dimen> + <dimen name="notification_right_icon_size">48dp</dimen> <!-- The top and bottom margin of the right icon in the normal notification states --> - <dimen name="notification_right_icon_headerless_margin">12dp</dimen> + <dimen name="notification_right_icon_headerless_margin">20dp</dimen> <!-- The top margin of the right icon in the "big" notification states --> + <!-- TODO(b/181048615): Move the large icon below the expander in big 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> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 7ad05de1bdd0..a4dec227ad9a 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2895,8 +2895,6 @@ <java-symbol type="id" name="alternate_expand_target" /> <java-symbol type="id" name="notification_header" /> <java-symbol type="id" name="notification_top_line" /> - <java-symbol type="id" name="notification_headerless_margin_extra_top" /> - <java-symbol type="id" name="notification_headerless_margin_extra_bottom" /> <java-symbol type="id" name="time_divider" /> <java-symbol type="id" name="header_text_divider" /> <java-symbol type="id" name="header_text_secondary_divider" /> @@ -2918,8 +2916,8 @@ <java-symbol type="dimen" name="notification_header_icon_size" /> <java-symbol type="dimen" name="notification_header_app_name_margin_start" /> <java-symbol type="dimen" name="notification_header_separating_margin" /> - <java-symbol type="dimen" name="notification_headerless_margin_constrained_minimum" /> - <java-symbol type="dimen" name="notification_headerless_margin_constrained_extra" /> + <java-symbol type="dimen" name="notification_headerless_margin_oneline" /> + <java-symbol type="dimen" name="notification_headerless_margin_twoline" /> <java-symbol type="string" name="default_notification_channel_label" /> <java-symbol type="string" name="importance_from_user" /> <java-symbol type="string" name="importance_from_person" /> |