Merge "use new theme colors on custom notifications"

This commit is contained in:
Lucas Dupin
2020-12-09 22:52:13 +00:00
committed by Android (Google) Code Review
6 changed files with 67 additions and 2 deletions

View File

@@ -489,7 +489,6 @@
<style name="TextAppearance.NotificationInfo">
<item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:textColor">@color/notification_primary_text_color</item>
</style>
<style name="TextAppearance.NotificationInfo.Secondary">
@@ -498,7 +497,6 @@
</style>
<style name="TextAppearance.NotificationInfo.Title">
<item name="android:textColor">@color/notification_primary_text_color</item>
<item name="android:textStyle">bold</item>
</style>

View File

@@ -47,6 +47,10 @@ public class NotificationCustomViewWrapper extends NotificationViewWrapper {
public void onContentUpdated(ExpandableNotificationRow row) {
super.onContentUpdated(row);
// Custom views will most likely use just white or black as their text color.
// We need to scan through and replace these colors by Material NEXT colors.
ensureThemeOnChildren();
// Let's invert the notification colors when we're in night mode and
// the notification background isn't colorized.
if (needsInversion(mBackgroundColor, mView)) {

View File

@@ -43,6 +43,11 @@ public class NotificationDecoratedCustomViewWrapper extends NotificationTemplate
if (childIndex != null && childIndex != -1) {
mWrappedView = container.getChildAt(childIndex);
}
// Custom views will most likely use just white or black as their text color.
// We need to scan through and replace these colors by Material NEXT colors.
ensureThemeOnChildren();
if (needsInversion(resolveBackgroundColor(), mWrappedView)) {
invertViewLuminosity(mWrappedView);
}

View File

@@ -29,11 +29,13 @@ import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.view.ContextThemeWrapper;
import android.view.NotificationHeaderView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.ColorUtils;
import com.android.internal.util.ContrastColorUtil;
@@ -55,6 +57,9 @@ public abstract class NotificationViewWrapper implements TransformableView {
private final Rect mTmpRect = new Rect();
protected int mBackgroundColor = 0;
private int mLightTextColor;
private int mDarkTextColor;
private int mDefaultTextColor;
public static NotificationViewWrapper wrap(Context ctx, View v, ExpandableNotificationRow row) {
if (v.getId() == com.android.internal.R.id.status_bar_latest_event_content) {
@@ -110,6 +115,15 @@ public abstract class NotificationViewWrapper implements TransformableView {
mBackgroundColor = backgroundColor;
mView.setBackground(new ColorDrawable(Color.TRANSPARENT));
}
mLightTextColor = mView.getContext().getColor(
com.android.internal.R.color.notification_primary_text_color_light);
mDarkTextColor = mView.getContext().getColor(
R.color.notification_primary_text_color_dark);
Context themedContext = new ContextThemeWrapper(mView.getContext(),
R.style.Theme_DeviceDefault_DayNight);
mDefaultTextColor = Utils.getColorAttr(themedContext, R.attr.textColorPrimary)
.getDefaultColor();
}
protected boolean needsInversion(int defaultBackgroundColor, View view) {
@@ -187,6 +201,42 @@ public abstract class NotificationViewWrapper implements TransformableView {
return false;
}
protected void ensureThemeOnChildren() {
if (mView == null) {
return;
}
// Notifications with custom backgrounds should not be adjusted
if (mBackgroundColor != Color.TRANSPARENT
|| getBackgroundColor(mView) != Color.TRANSPARENT) {
return;
}
// Now let's check if there's unprotected text somewhere, and apply the theme if we find it.
if (!(mView instanceof ViewGroup)) {
return;
}
processChildrenTextColor((ViewGroup) mView);
}
private void processChildrenTextColor(ViewGroup viewGroup) {
if (viewGroup == null) {
return;
}
for (int i = 0; i < viewGroup.getChildCount(); i++) {
View child = viewGroup.getChildAt(i);
if (child instanceof TextView) {
int foreground = ((TextView) child).getCurrentTextColor();
if (foreground == mLightTextColor || foreground == mDarkTextColor) {
((TextView) child).setTextColor(mDefaultTextColor);
}
} else if (child instanceof ViewGroup) {
processChildrenTextColor((ViewGroup) child);
}
}
}
protected int getBackgroundColor(View view) {
if (view == null) {
return Color.TRANSPARENT;

View File

@@ -81,12 +81,15 @@ public class NotificationContentViewTest extends SysuiTestCase {
View mockContracted = mock(NotificationHeaderView.class);
when(mockContracted.findViewById(com.android.internal.R.id.feedback))
.thenReturn(mockContracted);
when(mockContracted.getContext()).thenReturn(mContext);
View mockExpanded = mock(NotificationHeaderView.class);
when(mockExpanded.findViewById(com.android.internal.R.id.feedback))
.thenReturn(mockExpanded);
when(mockExpanded.getContext()).thenReturn(mContext);
View mockHeadsUp = mock(NotificationHeaderView.class);
when(mockHeadsUp.findViewById(com.android.internal.R.id.feedback))
.thenReturn(mockHeadsUp);
when(mockHeadsUp.getContext()).thenReturn(mContext);
mView.setContractedChild(mockContracted);
mView.setExpandedChild(mockExpanded);
@@ -107,18 +110,21 @@ public class NotificationContentViewTest extends SysuiTestCase {
when(mockContracted.animate()).thenReturn(mock(ViewPropertyAnimator.class));
when(mockContracted.findViewById(com.android.internal.R.id.expand_button)).thenReturn(
mockContractedEB);
when(mockContracted.getContext()).thenReturn(mContext);
View mockExpandedEB = mock(NotificationExpandButton.class);
View mockExpanded = mock(NotificationHeaderView.class);
when(mockExpanded.animate()).thenReturn(mock(ViewPropertyAnimator.class));
when(mockExpanded.findViewById(com.android.internal.R.id.expand_button)).thenReturn(
mockExpandedEB);
when(mockExpanded.getContext()).thenReturn(mContext);
View mockHeadsUpEB = mock(NotificationExpandButton.class);
View mockHeadsUp = mock(NotificationHeaderView.class);
when(mockHeadsUp.animate()).thenReturn(mock(ViewPropertyAnimator.class));
when(mockHeadsUp.findViewById(com.android.internal.R.id.expand_button)).thenReturn(
mockHeadsUpEB);
when(mockHeadsUp.getContext()).thenReturn(mContext);
// Set up all 3 child forms
mView.setContractedChild(mockContracted);

View File

@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.notification.row.wrapper;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.testing.AndroidTestingRunner;
@@ -49,6 +50,7 @@ public class NotificationViewWrapperTest extends SysuiTestCase {
public void setup() throws Exception {
allowTestableLooperAsMainThread();
mView = mock(View.class);
when(mView.getContext()).thenReturn(mContext);
NotificationTestHelper helper = new NotificationTestHelper(
mContext,
mDependency,