diff options
| author | Jeff DeCew <jeffdq@google.com> | 2020-10-21 09:44:49 -0400 |
|---|---|---|
| committer | Jeff DeCew <jeffdq@google.com> | 2020-10-21 10:32:19 -0400 |
| commit | 858ad2ac335d6d971efcaba9ec692a12377778f7 (patch) | |
| tree | 304931612482227906ac0737a5b8785c5168a874 /core/java | |
| parent | 73e65d429144732c45cf1d48299960d6eec7e4a4 (diff) | |
Minimize use of header in adjusting notification colors.
Also adds support for 'inverted' icons.
Test: atest SystemUITests
Test: manual testing of numerous notification configurations
Change-Id: I6fd9aeec9f5971495d514add2bbb30b50db7d3c1
Diffstat (limited to 'core/java')
5 files changed, 124 insertions, 26 deletions
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index a54c65e873ec..5e50b96a23d5 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -82,7 +82,6 @@ import android.util.Pair; import android.util.SparseArray; import android.util.proto.ProtoOutputStream; import android.view.Gravity; -import android.view.NotificationHeaderView; import android.view.View; import android.view.ViewGroup; import android.view.contentcapture.ContentCaptureContext; @@ -5862,24 +5861,16 @@ public class Notification implements Parcelable } /** - * Apply any necessariy colors to the small icon + * Apply any necessary colors to the small icon */ private void processSmallIconColor(Icon smallIcon, RemoteViews contentView, StandardTemplateParams p) { boolean colorable = !isLegacy() || getColorUtil().isGrayscaleIcon(mContext, smallIcon); - int color; - if (isColorized(p)) { - color = getPrimaryTextColor(p); - } else { - color = resolveContrastColor(p); - } - if (colorable) { - contentView.setDrawableTint(R.id.icon, false, color, - PorterDuff.Mode.SRC_ATOP); - - } + int color = isColorized(p) ? getPrimaryTextColor(p) : resolveContrastColor(p); + contentView.setInt(R.id.icon, "setBackgroundColor", + resolveBackgroundColor(p)); contentView.setInt(R.id.icon, "setOriginalIconColor", - colorable ? color : NotificationHeaderView.NO_COLOR); + colorable ? color : COLOR_INVALID); } /** @@ -5892,8 +5883,8 @@ public class Notification implements Parcelable if (largeIcon != null && isLegacy() && getColorUtil().isGrayscaleIcon(mContext, largeIcon)) { // resolve color will fall back to the default when legacy - contentView.setDrawableTint(R.id.icon, false, resolveContrastColor(p), - PorterDuff.Mode.SRC_ATOP); + int color = resolveContrastColor(p); + contentView.setInt(R.id.icon, "setOriginalIconColor", color); } } diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java index e28b6726611e..355b314a0b8f 100644 --- a/core/java/android/view/NotificationHeaderView.java +++ b/core/java/android/view/NotificationHeaderView.java @@ -17,7 +17,6 @@ package android.view; import android.annotation.Nullable; -import android.app.Notification; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.Resources; @@ -42,7 +41,6 @@ import java.util.ArrayList; */ @RemoteViews.RemoteView public class NotificationHeaderView extends ViewGroup { - public static final int NO_COLOR = Notification.COLOR_INVALID; private final int mChildMinWidth; private final int mContentEndMargin; private final int mGravity; @@ -294,14 +292,6 @@ public class NotificationHeaderView extends ViewGroup { updateTouchListener(); } - public int getOriginalIconColor() { - return mIcon.getOriginalIconColor(); - } - - public int getOriginalNotificationColor() { - return mExpandButton.getOriginalNotificationColor(); - } - public void setShowWorkBadgeAtEnd(boolean showWorkBadgeAtEnd) { if (showWorkBadgeAtEnd != mShowWorkBadgeAtEnd) { setClipToPadding(!showWorkBadgeAtEnd); diff --git a/core/java/com/android/internal/widget/CachingIconView.java b/core/java/com/android/internal/widget/CachingIconView.java index 84cde1b84e14..0bf323f8f493 100644 --- a/core/java/com/android/internal/widget/CachingIconView.java +++ b/core/java/com/android/internal/widget/CachingIconView.java @@ -16,12 +16,15 @@ package com.android.internal.widget; +import static com.android.internal.widget.ColoredIconHelper.applyGrayTint; + import android.annotation.DrawableRes; import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.Configuration; import android.graphics.Bitmap; +import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; import android.net.Uri; @@ -48,6 +51,7 @@ public class CachingIconView extends ImageView { private Consumer<Integer> mOnVisibilityChangedListener; private Consumer<Boolean> mOnForceHiddenChangedListener; private int mIconColor; + private int mBackgroundColor; private boolean mWillBeForceHidden; @UnsupportedAppUsage @@ -230,9 +234,55 @@ public class CachingIconView extends ImageView { return mForceHidden; } + /** + * Provides the notification's background color to the icon. This is only used when the icon + * is "inverted". This should be called before calling {@link #setOriginalIconColor(int)}. + */ + @RemotableViewMethod + public void setBackgroundColor(int color) { + mBackgroundColor = color; + } + + /** + * Sets the icon color. If COLOR_INVALID is set, the icon's color filter will + * not be altered. If there is a background drawable, this method uses the value from + * {@link #setBackgroundColor(int)} which must have been already called. + */ @RemotableViewMethod public void setOriginalIconColor(int color) { mIconColor = color; + Drawable background = getBackground(); + Drawable icon = getDrawable(); + boolean hasColor = color != ColoredIconHelper.COLOR_INVALID; + if (background == null) { + // This is the pre-S style -- colored icon with no background. + if (hasColor) { + icon.mutate().setColorFilter(color, PorterDuff.Mode.SRC_ATOP); + } + } else { + // When there is a background drawable, color it with the foreground color and + // colorize the icon itself with the background color, creating an inverted effect. + if (hasColor) { + background.mutate().setColorFilter(color, PorterDuff.Mode.SRC_ATOP); + icon.mutate().setColorFilter(mBackgroundColor, PorterDuff.Mode.SRC_ATOP); + } else { + background.mutate().setColorFilter(mBackgroundColor, PorterDuff.Mode.SRC_ATOP); + } + } + } + + /** + * Set the icon's color filter: to gray if true, otherwise colored. + * If this icon has no original color, this has no effect. + */ + public void setGrayedOut(boolean grayedOut) { + // If there is a background drawable, then it has the foreground color and the image + // drawable has the background color, creating an inverted efffect. + Drawable drawable = getBackground(); + if (drawable == null) { + drawable = getDrawable(); + } + applyGrayTint(mContext, drawable, grayedOut, mIconColor); } public int getOriginalIconColor() { diff --git a/core/java/com/android/internal/widget/ColoredIconHelper.java b/core/java/com/android/internal/widget/ColoredIconHelper.java new file mode 100644 index 000000000000..97e5e86d9e60 --- /dev/null +++ b/core/java/com/android/internal/widget/ColoredIconHelper.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2020 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.ColorInt; +import android.app.Notification; +import android.content.Context; +import android.content.res.Configuration; +import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; + +import com.android.internal.util.ContrastColorUtil; + +/** Helpers for colored icons */ +final class ColoredIconHelper { + + @ColorInt + static final int COLOR_INVALID = Notification.COLOR_INVALID; + + private ColoredIconHelper() { + } + + /** + * Apply a gray tint or the original color to a drawable, accounting for the night mode in + * selecting the gray. + */ + static void applyGrayTint(Context ctx, Drawable drawable, boolean apply, int originalColor) { + if (originalColor == COLOR_INVALID) { + return; + } + if (apply) { + // lets gray it out + Configuration config = ctx.getResources().getConfiguration(); + boolean inNightMode = (config.uiMode & Configuration.UI_MODE_NIGHT_MASK) + == Configuration.UI_MODE_NIGHT_YES; + int grey = ContrastColorUtil.resolveColor(ctx, Notification.COLOR_DEFAULT, inNightMode); + drawable.mutate().setColorFilter(grey, PorterDuff.Mode.SRC_ATOP); + } else { + // lets reset it + drawable.mutate().setColorFilter(originalColor, PorterDuff.Mode.SRC_ATOP); + } + } +} diff --git a/core/java/com/android/internal/widget/NotificationExpandButton.java b/core/java/com/android/internal/widget/NotificationExpandButton.java index af6ac07851c0..986412d2ce5d 100644 --- a/core/java/com/android/internal/widget/NotificationExpandButton.java +++ b/core/java/com/android/internal/widget/NotificationExpandButton.java @@ -16,6 +16,8 @@ package com.android.internal.widget; +import static com.android.internal.widget.ColoredIconHelper.applyGrayTint; + import android.annotation.Nullable; import android.content.Context; import android.graphics.Rect; @@ -70,6 +72,14 @@ public class NotificationExpandButton extends ImageView { return mOriginalNotificationColor; } + /** + * Set the button's color filter: to gray if true, otherwise colored. + * If this button has no original color, this has no effect. + */ + public void setGrayedOut(boolean shouldApply) { + applyGrayTint(mContext, getDrawable(), shouldApply, mOriginalNotificationColor); + } + private void extendRectToMinTouchSize(Rect rect) { int touchTargetSize = (int) (getResources().getDisplayMetrics().density * 48); rect.left = rect.centerX() - touchTargetSize / 2; |
