Split the reply icon permanently from the right icon
Previously these would overlap, but they are now completely
separate.
Test: ensure that all notification styles still work with the new affordance.
Change-Id: I16f5f863b4afac27494a4a7615631bca240ca532
Fixes: 72750728
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 4f88a03..a69bd8d 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -4278,7 +4278,6 @@
private void resetStandardTemplate(RemoteViews contentView) {
resetNotificationHeader(contentView);
- resetContentMargins(contentView);
contentView.setViewVisibility(R.id.right_icon, View.GONE);
contentView.setViewVisibility(R.id.title, View.GONE);
contentView.setTextViewText(R.id.title, null);
@@ -4310,24 +4309,23 @@
mN.mUsesStandardHeader = false;
}
- private void resetContentMargins(RemoteViews contentView) {
- contentView.setViewLayoutMarginEndDimen(R.id.line1, 0);
- contentView.setViewLayoutMarginEndDimen(R.id.text, 0);
- }
-
- private RemoteViews applyStandardTemplate(int resId) {
- return applyStandardTemplate(resId, mParams.reset().fillTextsFrom(this));
+ private RemoteViews applyStandardTemplate(int resId, TemplateBindResult result) {
+ return applyStandardTemplate(resId, mParams.reset().fillTextsFrom(this),
+ result);
}
/**
* @param hasProgress whether the progress bar should be shown and set
+ * @param result
*/
- private RemoteViews applyStandardTemplate(int resId, boolean hasProgress) {
+ private RemoteViews applyStandardTemplate(int resId, boolean hasProgress,
+ TemplateBindResult result) {
return applyStandardTemplate(resId, mParams.reset().hasProgress(hasProgress)
- .fillTextsFrom(this));
+ .fillTextsFrom(this), result);
}
- private RemoteViews applyStandardTemplate(int resId, StandardTemplateParams p) {
+ private RemoteViews applyStandardTemplate(int resId, StandardTemplateParams p,
+ TemplateBindResult result) {
RemoteViews contentView = new BuilderRemoteViews(mContext.getApplicationInfo(), resId);
resetStandardTemplate(contentView);
@@ -4335,7 +4333,7 @@
final Bundle ex = mN.extras;
updateBackgroundColor(contentView);
bindNotificationHeader(contentView, p.ambient, p.headerTextSecondary);
- bindLargeIcon(contentView, p.hideLargeIcon || p.ambient, p.alwaysShowReply);
+ bindLargeIconAndReply(contentView, p, result);
boolean showProgress = handleProgressBar(p.hasProgress, contentView, ex);
if (p.title != null) {
contentView.setViewVisibility(R.id.title, View.VISIBLE);
@@ -4531,8 +4529,31 @@
}
}
- private void bindLargeIcon(RemoteViews contentView, boolean hideLargeIcon,
- boolean alwaysShowReply) {
+ private void bindLargeIconAndReply(RemoteViews contentView, StandardTemplateParams p,
+ TemplateBindResult result) {
+ boolean largeIconShown = bindLargeIcon(contentView, p.hideLargeIcon || p.ambient);
+ boolean showReplyIcon = bindReplyIcon(contentView, p.hideReplyIcon || p.ambient);
+ contentView.setViewVisibility(R.id.right_icon_container,
+ largeIconShown || showReplyIcon ? View.VISIBLE : View.GONE);
+ int marginEndDimen = 0;
+ if (largeIconShown && showReplyIcon) {
+ marginEndDimen = R.dimen.notification_content_picture_and_reply_margin;
+ } else if (largeIconShown || showReplyIcon) {
+ marginEndDimen = R.dimen.notification_content_picture_margin;
+ }
+ contentView.setViewLayoutMarginEndDimen(R.id.line1, marginEndDimen);
+ contentView.setViewLayoutMarginEndDimen(R.id.text, marginEndDimen);
+ contentView.setViewLayoutMarginEndDimen(R.id.progress, marginEndDimen);
+ if (result != null) {
+ result.setIconMarginEndDimen(marginEndDimen);
+ }
+ }
+
+ /**
+ * Bind the large icon.
+ * @return if the largeIcon is visible
+ */
+ private boolean bindLargeIcon(RemoteViews contentView, boolean hideLargeIcon) {
if (mN.mLargeIcon == null && mN.largeIcon != null) {
mN.mLargeIcon = Icon.createWithBitmap(mN.largeIcon);
}
@@ -4541,51 +4562,35 @@
contentView.setViewVisibility(R.id.right_icon, View.VISIBLE);
contentView.setImageViewIcon(R.id.right_icon, mN.mLargeIcon);
processLargeLegacyIcon(mN.mLargeIcon, contentView);
- int endMargin = R.dimen.notification_content_picture_margin;
- contentView.setViewLayoutMarginEndDimen(R.id.line1, endMargin);
- contentView.setViewLayoutMarginEndDimen(R.id.text, endMargin);
- contentView.setViewLayoutMarginEndDimen(R.id.progress, endMargin);
}
- // Bind the reply action
- Action action = findReplyAction();
+ return showLargeIcon;
+ }
- boolean actionVisible = action != null && (showLargeIcon || alwaysShowReply);
- int replyId = showLargeIcon ? R.id.reply_icon_action : R.id.right_icon;
+ /**
+ * Bind the reply icon.
+ * @return if the reply icon is visible
+ */
+ private boolean bindReplyIcon(RemoteViews contentView, boolean hideReplyIcon) {
+ boolean actionVisible = !hideReplyIcon;
+ Action action = null;
if (actionVisible) {
- // We're only showing the icon as big if we're hiding the large icon
- int contrastColor = resolveContrastColor();
- int iconColor;
- if (showLargeIcon) {
- contentView.setDrawableTint(R.id.reply_icon_action,
- true /* targetBackground */,
- contrastColor, PorterDuff.Mode.SRC_ATOP);
- contentView.setOnClickPendingIntent(R.id.right_icon,
- action.actionIntent);
- contentView.setRemoteInputs(R.id.right_icon, action.mRemoteInputs);
- iconColor = NotificationColorUtil.isColorLight(contrastColor)
- ? Color.BLACK : Color.WHITE;
- } else {
- contentView.setImageViewResource(R.id.right_icon,
- R.drawable.ic_reply_notification_large);
- contentView.setViewVisibility(R.id.right_icon, View.VISIBLE);
- iconColor = contrastColor;
- }
- contentView.setDrawableTint(replyId,
- false /* targetBackground */,
- iconColor,
- PorterDuff.Mode.SRC_ATOP);
- contentView.setOnClickPendingIntent(replyId,
- action.actionIntent);
- contentView.setRemoteInputs(replyId, action.mRemoteInputs);
- } else {
- contentView.setRemoteInputs(R.id.right_icon, null);
+ action = findReplyAction();
+ actionVisible = action != null;
}
- contentView.setViewVisibility(R.id.reply_icon_action, actionVisible && showLargeIcon
- ? View.VISIBLE
- : View.GONE);
- contentView.setViewVisibility(R.id.right_icon_container, actionVisible || showLargeIcon
- ? View.VISIBLE
- : View.GONE);
+ if (actionVisible) {
+ contentView.setViewVisibility(R.id.reply_icon_action, View.VISIBLE);
+ contentView.setDrawableTint(R.id.reply_icon_action,
+ false /* targetBackground */,
+ getPrimaryTextColor(),
+ PorterDuff.Mode.SRC_ATOP);
+ contentView.setOnClickPendingIntent(R.id.reply_icon_action, action.actionIntent);
+ contentView.setRemoteInputs(R.id.reply_icon_action, action.mRemoteInputs);
+ } else {
+ contentView.setRemoteInputs(R.id.reply_icon_action, null);
+ }
+ contentView.setViewVisibility(R.id.reply_icon_action,
+ actionVisible ? View.VISIBLE : View.GONE);
+ return actionVisible;
}
private Action findReplyAction() {
@@ -4770,13 +4775,15 @@
R.dimen.notification_content_margin);
}
- private RemoteViews applyStandardTemplateWithActions(int layoutId) {
- return applyStandardTemplateWithActions(layoutId, mParams.reset().fillTextsFrom(this));
+ private RemoteViews applyStandardTemplateWithActions(int layoutId,
+ TemplateBindResult result) {
+ return applyStandardTemplateWithActions(layoutId, mParams.reset().fillTextsFrom(this),
+ result);
}
private RemoteViews applyStandardTemplateWithActions(int layoutId,
- StandardTemplateParams p) {
- RemoteViews big = applyStandardTemplate(layoutId, p);
+ StandardTemplateParams p, TemplateBindResult result) {
+ RemoteViews big = applyStandardTemplate(layoutId, p, result);
resetStandardTemplateWithActions(big);
@@ -4883,7 +4890,7 @@
return styleView;
}
}
- return applyStandardTemplate(getBaseLayoutResource());
+ return applyStandardTemplate(getBaseLayoutResource(), null /* result */);
}
private boolean useExistingRemoteView() {
@@ -4902,7 +4909,8 @@
result = mStyle.makeBigContentView();
hideLine1Text(result);
} else if (mActions.size() != 0) {
- result = applyStandardTemplateWithActions(getBigBaseLayoutResource());
+ result = applyStandardTemplateWithActions(getBigBaseLayoutResource(),
+ null /* result */);
}
makeHeaderExpanded(result);
return result;
@@ -4939,7 +4947,8 @@
public RemoteViews makeAmbientNotification() {
RemoteViews ambient = applyStandardTemplateWithActions(
R.layout.notification_template_material_ambient,
- mParams.reset().ambient(true).fillTextsFrom(this).hasProgress(false));
+ mParams.reset().ambient(true).fillTextsFrom(this).hasProgress(false),
+ null /* result */);
return ambient;
}
@@ -4982,7 +4991,7 @@
return null;
}
- return applyStandardTemplateWithActions(getBigBaseLayoutResource());
+ return applyStandardTemplateWithActions(getBigBaseLayoutResource(), null /* result */);
}
/**
@@ -5863,6 +5872,18 @@
}
protected RemoteViews getStandardView(int layoutId) {
+ return getStandardView(layoutId, null);
+ }
+
+ /**
+ * Get the standard view for this style.
+ *
+ * @param layoutId The layout id to use
+ * @param result The result where template bind information is saved.
+ * @return A remoteView for this style.
+ * @hide
+ */
+ protected RemoteViews getStandardView(int layoutId, TemplateBindResult result) {
checkBuilder();
// Nasty.
@@ -5872,7 +5893,7 @@
mBuilder.setContentTitle(mBigContentTitle);
}
- RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(layoutId);
+ RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(layoutId, result);
mBuilder.getAllExtras().putCharSequence(EXTRA_TITLE, oldBuilderContentTitle);
@@ -6169,7 +6190,8 @@
mBuilder.mN.largeIcon = null;
}
- RemoteViews contentView = getStandardView(mBuilder.getBigPictureLayoutResource());
+ RemoteViews contentView = getStandardView(mBuilder.getBigPictureLayoutResource(),
+ null /* result */);
if (mSummaryTextSet) {
contentView.setTextViewText(R.id.text, mBuilder.processTextSpans(
mBuilder.processLegacyText(mSummaryText)));
@@ -6356,7 +6378,9 @@
CharSequence text = mBuilder.getAllExtras().getCharSequence(EXTRA_TEXT);
mBuilder.getAllExtras().putCharSequence(EXTRA_TEXT, null);
- RemoteViews contentView = getStandardView(mBuilder.getBigTextLayoutResource());
+ TemplateBindResult result = new TemplateBindResult();
+ RemoteViews contentView = getStandardView(mBuilder.getBigTextLayoutResource(), result);
+ contentView.setInt(R.id.big_text, "setImageEndMarginDimen", result.getIconMarginEndDimen());
mBuilder.getAllExtras().putCharSequence(EXTRA_TEXT, text);
@@ -6739,7 +6763,7 @@
mBuilder.mOriginalActions = mBuilder.mActions;
mBuilder.mActions = new ArrayList<>();
RemoteViews remoteViews = makeMessagingView(true /* displayImagesAtEnd */,
- true /* showReplyIcon */);
+ false /* hideLargeIcon */);
mBuilder.mActions = mBuilder.mOriginalActions;
mBuilder.mOriginalActions = null;
return remoteViews;
@@ -6826,7 +6850,7 @@
*/
@Override
public RemoteViews makeBigContentView() {
- return makeMessagingView(false /* displayImagesAtEnd */, false /* showReplyIcon */);
+ return makeMessagingView(false /* displayImagesAtEnd */, true /* hideLargeIcon */);
}
/**
@@ -6834,11 +6858,11 @@
*
* @param displayImagesAtEnd should images be displayed at the end of the content instead
* of inline.
- * @param showReplyIcon Should the reply affordance be shown at the end of the notification
+ * @param hideRightIcons Should the reply affordance be shown at the end of the notification
* @return the created remoteView.
*/
@NonNull
- private RemoteViews makeMessagingView(boolean displayImagesAtEnd, boolean showReplyIcon) {
+ private RemoteViews makeMessagingView(boolean displayImagesAtEnd, boolean hideRightIcons) {
CharSequence conversationTitle = !TextUtils.isEmpty(super.mBigContentTitle)
? super.mBigContentTitle
: mConversationTitle;
@@ -6849,20 +6873,18 @@
nameReplacement = conversationTitle;
conversationTitle = null;
}
- boolean hideLargeIcon = !showReplyIcon || isOneToOne;
+ TemplateBindResult bindResult = new TemplateBindResult();
RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(
mBuilder.getMessagingLayoutResource(),
mBuilder.mParams.reset().hasProgress(false).title(conversationTitle).text(null)
- .hideLargeIcon(hideLargeIcon)
- .headerTextSecondary(conversationTitle)
- .alwaysShowReply(showReplyIcon));
+ .hideLargeIcon(hideRightIcons || isOneToOne)
+ .hideReplyIcon(hideRightIcons)
+ .headerTextSecondary(conversationTitle),
+ bindResult);
addExtras(mBuilder.mN.extras);
// also update the end margin if there is an image
- int endMargin = R.dimen.notification_content_margin_end;
- if (showReplyIcon) {
- endMargin = R.dimen.notification_content_plus_picture_margin_end;
- }
- contentView.setViewLayoutMarginEndDimen(R.id.notification_main_column, endMargin);
+ contentView.setViewLayoutMarginEndDimen(R.id.notification_main_column,
+ bindResult.getIconMarginEndDimen());
contentView.setInt(R.id.status_bar_latest_event_content, "setLayoutColor",
mBuilder.resolveContrastColor());
contentView.setBoolean(R.id.status_bar_latest_event_content, "setDisplayImagesAtEnd",
@@ -6934,7 +6956,7 @@
@Override
public RemoteViews makeHeadsUpContentView(boolean increasedHeight) {
RemoteViews remoteViews = makeMessagingView(true /* displayImagesAtEnd */,
- false /* showReplyIcon */);
+ true /* hideLargeIcon */);
remoteViews.setInt(R.id.notification_messaging, "setMaxDisplayedLines", 1);
return remoteViews;
}
@@ -7275,7 +7297,8 @@
CharSequence oldBuilderContentText = mBuilder.mN.extras.getCharSequence(EXTRA_TEXT);
mBuilder.getAllExtras().putCharSequence(EXTRA_TEXT, null);
- RemoteViews contentView = getStandardView(mBuilder.getInboxLayoutResource());
+ TemplateBindResult result = new TemplateBindResult();
+ RemoteViews contentView = getStandardView(mBuilder.getInboxLayoutResource(), result);
mBuilder.getAllExtras().putCharSequence(EXTRA_TEXT, oldBuilderContentText);
@@ -7304,7 +7327,8 @@
mBuilder.processTextSpans(mBuilder.processLegacyText(str)));
mBuilder.setTextViewColorSecondary(contentView, rowIds[i]);
contentView.setViewPadding(rowIds[i], 0, topPadding, 0, 0);
- handleInboxImageMargin(contentView, rowIds[i], first);
+ handleInboxImageMargin(contentView, rowIds[i], first,
+ result.getIconMarginEndDimen());
if (first) {
onlyViewId = rowIds[i];
} else {
@@ -7336,14 +7360,15 @@
return !Objects.equals(getLines(), newS.getLines());
}
- private void handleInboxImageMargin(RemoteViews contentView, int id, boolean first) {
+ private void handleInboxImageMargin(RemoteViews contentView, int id, boolean first,
+ int marginEndDimen) {
int endMargin = 0;
if (first) {
final int max = mBuilder.mN.extras.getInt(EXTRA_PROGRESS_MAX, 0);
final boolean ind = mBuilder.mN.extras.getBoolean(EXTRA_PROGRESS_INDETERMINATE);
boolean hasProgress = max != 0 || ind;
- if (mBuilder.mN.hasLargeIcon() && !hasProgress) {
- endMargin = R.dimen.notification_content_picture_margin;
+ if (!hasProgress) {
+ endMargin = marginEndDimen;
}
}
contentView.setViewLayoutMarginEndDimen(id, endMargin);
@@ -7535,7 +7560,8 @@
private RemoteViews makeMediaContentView() {
RemoteViews view = mBuilder.applyStandardTemplate(
- R.layout.notification_template_material_media, false /* hasProgress */);
+ R.layout.notification_template_material_media, false, /* hasProgress */
+ null /* result */);
final int numActions = mBuilder.mActions.size();
final int N = mActionsToShowInCompact == null
@@ -7559,7 +7585,7 @@
// handle the content margin
int endMargin = R.dimen.notification_content_margin_end;
if (mBuilder.mN.hasLargeIcon()) {
- endMargin = R.dimen.notification_content_plus_picture_margin_end;
+ endMargin = R.dimen.notification_media_image_margin_end;
}
view.setViewLayoutMarginEndDimen(R.id.notification_main_column, endMargin);
return view;
@@ -7580,8 +7606,7 @@
return null;
}
RemoteViews big = mBuilder.applyStandardTemplate(
- R.layout.notification_template_material_big_media,
- false);
+ R.layout.notification_template_material_big_media, false, null /* result */);
if (actionCount > 0) {
big.removeAllViews(com.android.internal.R.id.media_actions);
@@ -7677,16 +7702,18 @@
if (mBuilder.mActions.size() == 0) {
return makeStandardTemplateWithCustomContent(headsUpContentView);
}
+ TemplateBindResult result = new TemplateBindResult();
RemoteViews remoteViews = mBuilder.applyStandardTemplateWithActions(
- mBuilder.getBigBaseLayoutResource());
- buildIntoRemoteViewContent(remoteViews, headsUpContentView);
+ mBuilder.getBigBaseLayoutResource(), result);
+ buildIntoRemoteViewContent(remoteViews, headsUpContentView, result);
return remoteViews;
}
private RemoteViews makeStandardTemplateWithCustomContent(RemoteViews customContent) {
+ TemplateBindResult result = new TemplateBindResult();
RemoteViews remoteViews = mBuilder.applyStandardTemplate(
- mBuilder.getBaseLayoutResource());
- buildIntoRemoteViewContent(remoteViews, customContent);
+ mBuilder.getBaseLayoutResource(), result);
+ buildIntoRemoteViewContent(remoteViews, customContent, result);
return remoteViews;
}
@@ -7697,14 +7724,15 @@
if (mBuilder.mActions.size() == 0) {
return makeStandardTemplateWithCustomContent(bigContentView);
}
+ TemplateBindResult result = new TemplateBindResult();
RemoteViews remoteViews = mBuilder.applyStandardTemplateWithActions(
- mBuilder.getBigBaseLayoutResource());
- buildIntoRemoteViewContent(remoteViews, bigContentView);
+ mBuilder.getBigBaseLayoutResource(), result);
+ buildIntoRemoteViewContent(remoteViews, bigContentView, result);
return remoteViews;
}
private void buildIntoRemoteViewContent(RemoteViews remoteViews,
- RemoteViews customContent) {
+ RemoteViews customContent, TemplateBindResult result) {
if (customContent != null) {
// Need to clone customContent before adding, because otherwise it can no longer be
// parceled independently of remoteViews.
@@ -7714,11 +7742,14 @@
remoteViews.setReapplyDisallowed();
}
// also update the end margin if there is an image
- int endMargin = R.dimen.notification_content_margin_end;
- if (mBuilder.mN.hasLargeIcon()) {
- endMargin = R.dimen.notification_content_plus_picture_margin_end;
+ Resources resources = mBuilder.mContext.getResources();
+ int endMargin = resources.getDimensionPixelSize(
+ R.dimen.notification_content_margin_end);
+ int marginEndDimen = result.getIconMarginEndDimen();
+ if (marginEndDimen != 0) {
+ endMargin += resources.getDimensionPixelSize(marginEndDimen);
}
- remoteViews.setViewLayoutMarginEndDimen(R.id.notification_main_column, endMargin);
+ remoteViews.setViewLayoutMarginEnd(R.id.notification_main_column, endMargin);
}
/**
@@ -9322,6 +9353,25 @@
}
}
+ /**
+ * A result object where information about the template that was created is saved.
+ */
+ private static class TemplateBindResult {
+ int mIconMarginEndDimen;
+
+ /**
+ * Get the margin end dimension that needs to be added to any fields that may overlap
+ * with the right actions.
+ */
+ public int getIconMarginEndDimen() {
+ return mIconMarginEndDimen;
+ }
+
+ public void setIconMarginEndDimen(int iconMarginEndDimen) {
+ this.mIconMarginEndDimen = iconMarginEndDimen;
+ }
+ }
+
private static class StandardTemplateParams {
boolean hasProgress = true;
boolean ambient = false;
@@ -9329,7 +9379,7 @@
CharSequence text;
CharSequence headerTextSecondary;
boolean hideLargeIcon;
- public boolean alwaysShowReply;
+ boolean hideReplyIcon;
final StandardTemplateParams reset() {
hasProgress = true;
@@ -9360,13 +9410,13 @@
return this;
}
- final StandardTemplateParams alwaysShowReply(boolean alwaysShowReply) {
- this.alwaysShowReply = alwaysShowReply;
+ final StandardTemplateParams hideLargeIcon(boolean hideLargeIcon) {
+ this.hideLargeIcon = hideLargeIcon;
return this;
}
- final StandardTemplateParams hideLargeIcon(boolean hideLargeIcon) {
- this.hideLargeIcon = hideLargeIcon;
+ final StandardTemplateParams hideReplyIcon(boolean hideReplyIcon) {
+ this.hideReplyIcon = hideReplyIcon;
return this;
}