Collapsed DecoratedCustomView notifications show app name instead of title.

Previously, we never showed a title in the decorations, and
we still don't in the expanded decorations.  Rather than
making devleopers deal with the discrepancy, it's easier to
just show the app name for these views.  It makes them a
tad less desirable, but we could potentially give developers
a flag to opt into the title in the future.

Bug: 163626038
Bug: 173528244
Bug: 173742646
Test: manual
Change-Id: I8e5fe162c1ccdddcd39ea36f2b28fcc6aefd1f83
This commit is contained in:
Jeff DeCew
2020-11-19 19:57:20 -05:00
parent 370a2ce7d7
commit fa5c76c245
5 changed files with 71 additions and 36 deletions

View File

@@ -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() {
@@ -5521,8 +5517,11 @@ public class Notification implements Parcelable
hideLine1Text(result);
}
if (result == null && bigContentViewRequired()) {
result = applyStandardTemplateWithActions(getBigBaseLayoutResource(),
StandardTemplateParams.VIEW_TYPE_BIG, null /* result */);
StandardTemplateParams p = mParams.reset()
.viewType(StandardTemplateParams.VIEW_TYPE_BIG)
.fillTextsFrom(this);
result = applyStandardTemplateWithActions(getBigBaseLayoutResource(), p,
null /* result */);
}
makeHeaderExpanded(result);
return result;
@@ -8703,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;
}
@@ -8724,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;
}
@@ -11039,6 +11047,7 @@ public class Notification implements Parcelable
int mViewType = VIEW_TYPE_UNSPECIFIED;
boolean mHeaderless;
boolean mHasCustomContent;
boolean hasProgress = true;
CharSequence title;
CharSequence text;
@@ -11052,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;
@@ -11078,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;

View File

@@ -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>

View File

@@ -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"

View File

@@ -14,12 +14,22 @@
~ 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"

View File

@@ -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);
}
}
}