Loading core/java/android/app/Notification.java +66 −36 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } /** Loading Loading @@ -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) Loading Loading @@ -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)); } } Loading Loading @@ -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; } } } Loading core/res/res/layout/notification_template_header.xml +12 −0 Original line number Diff line number Diff line Loading @@ -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" Loading core/res/res/layout/notification_template_material_base.xml +13 −1 Original line number Diff line number Diff line Loading @@ -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" Loading @@ -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" Loading core/res/res/values/dimens.xml +4 −0 Original line number Diff line number Diff line Loading @@ -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> Loading core/res/res/values/ids.xml +6 −0 Original line number Diff line number Diff line Loading @@ -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" /> Loading Loading
core/java/android/app/Notification.java +66 −36 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } /** Loading Loading @@ -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) Loading Loading @@ -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)); } } Loading Loading @@ -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; } } } Loading
core/res/res/layout/notification_template_header.xml +12 −0 Original line number Diff line number Diff line Loading @@ -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" Loading
core/res/res/layout/notification_template_material_base.xml +13 −1 Original line number Diff line number Diff line Loading @@ -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" Loading @@ -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" Loading
core/res/res/values/dimens.xml +4 −0 Original line number Diff line number Diff line Loading @@ -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> Loading
core/res/res/values/ids.xml +6 −0 Original line number Diff line number Diff line Loading @@ -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" /> Loading