diff options
10 files changed, 155 insertions, 39 deletions
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index b12ab75a5809..4802b29bdeec 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -39,7 +39,6 @@ import android.media.AudioManager; import android.media.session.MediaSession; import android.net.Uri; import android.os.BadParcelableException; -import android.os.BaseBundle; import android.os.Build; import android.os.Bundle; import android.os.Parcel; @@ -51,7 +50,9 @@ import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.TextUtils; import android.text.style.AbsoluteSizeSpan; +import android.text.style.BackgroundColorSpan; import android.text.style.CharacterStyle; +import android.text.style.ForegroundColorSpan; import android.text.style.RelativeSizeSpan; import android.text.style.TextAppearanceSpan; import android.util.ArraySet; @@ -73,7 +74,6 @@ import java.lang.annotation.RetentionPolicy; import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Set; @@ -3706,8 +3706,6 @@ public class Notification implements Parcelable emphazisedMode ? getEmphasizedActionLayoutResource() : tombstone ? getActionTombstoneLayoutResource() : getActionLayoutResource()); - final Icon ai = action.getIcon(); - button.setTextViewText(R.id.action0, processLegacyText(action.title)); if (!tombstone) { button.setOnClickPendingIntent(R.id.action0, action.actionIntent); } @@ -3716,14 +3714,29 @@ public class Notification implements Parcelable button.setRemoteInputs(R.id.action0, action.mRemoteInputs); } if (emphazisedMode) { - // change the background color - int color = resolveContrastColor(); - if (oddAction) { - color = NotificationColorUtil.lightenColor(color, 10); - } - button.setDrawableParameters(R.id.button_holder, true, -1, color, + // change the background bgColor + int bgColor = mContext.getColor(oddAction ? R.color.notification_action_list + : R.color.notification_action_list_dark); + button.setDrawableParameters(R.id.button_holder, true, -1, bgColor, PorterDuff.Mode.SRC_ATOP, -1); + CharSequence title = action.title; + ColorStateList[] outResultColor = null; + if (isLegacy()) { + title = clearColorSpans(title); + } else { + outResultColor = new ColorStateList[1]; + title = ensureColorSpanContrast(title, bgColor, outResultColor); + } + button.setTextViewText(R.id.action0, title); + if (outResultColor != null && outResultColor[0] != null) { + // We need to set the text color as well since changing a text to uppercase + // clears its spans. + button.setTextColor(R.id.action0, outResultColor[0]); + } else if (mN.color != COLOR_DEFAULT) { + button.setTextColor(R.id.action0,resolveContrastColor()); + } } else { + button.setTextViewText(R.id.action0, processLegacyText(action.title)); if (mN.color != COLOR_DEFAULT) { button.setTextColor(R.id.action0, resolveContrastColor()); } @@ -3732,6 +3745,112 @@ public class Notification implements Parcelable } /** + * Clears all color spans of a text + * @param charSequence the input text + * @return the same text but without color spans + */ + private CharSequence clearColorSpans(CharSequence charSequence) { + if (charSequence instanceof Spanned) { + Spanned ss = (Spanned) charSequence; + Object[] spans = ss.getSpans(0, ss.length(), Object.class); + SpannableStringBuilder builder = new SpannableStringBuilder(ss.toString()); + for (Object span : spans) { + Object resultSpan = span; + if (resultSpan instanceof CharacterStyle) { + resultSpan = ((CharacterStyle) span).getUnderlying(); + } + if (resultSpan instanceof TextAppearanceSpan) { + TextAppearanceSpan originalSpan = (TextAppearanceSpan) resultSpan; + if (originalSpan.getTextColor() != null) { + resultSpan = new TextAppearanceSpan( + originalSpan.getFamily(), + originalSpan.getTextStyle(), + originalSpan.getTextSize(), + null, + originalSpan.getLinkTextColor()); + } + } else if (resultSpan instanceof ForegroundColorSpan + || (resultSpan instanceof BackgroundColorSpan)) { + continue; + } else { + resultSpan = span; + } + builder.setSpan(resultSpan, ss.getSpanStart(span), ss.getSpanEnd(span), + ss.getSpanFlags(span)); + } + return builder; + } + return charSequence; + } + + /** + * Ensures contrast on color spans against a background color. also returns the color of the + * text if a span was found that spans over the whole text. + * + * @param charSequence the charSequence on which the spans are + * @param background the background color to ensure the contrast against + * @param outResultColor an array in which a color will be returned as the first element if + * there exists a full length color span. + * @return the contrasted charSequence + */ + private CharSequence ensureColorSpanContrast(CharSequence charSequence, int background, + ColorStateList[] outResultColor) { + if (charSequence instanceof Spanned) { + Spanned ss = (Spanned) charSequence; + Object[] spans = ss.getSpans(0, ss.length(), Object.class); + SpannableStringBuilder builder = new SpannableStringBuilder(ss.toString()); + for (Object span : spans) { + Object resultSpan = span; + int spanStart = ss.getSpanStart(span); + int spanEnd = ss.getSpanEnd(span); + boolean fullLength = (spanEnd - spanStart) == charSequence.length(); + if (resultSpan instanceof CharacterStyle) { + resultSpan = ((CharacterStyle) span).getUnderlying(); + } + if (resultSpan instanceof TextAppearanceSpan) { + TextAppearanceSpan originalSpan = (TextAppearanceSpan) resultSpan; + ColorStateList textColor = originalSpan.getTextColor(); + if (textColor != null) { + int[] colors = textColor.getColors(); + int[] newColors = new int[colors.length]; + for (int i = 0; i < newColors.length; i++) { + newColors[i] = NotificationColorUtil.ensureLargeTextContrast( + colors[i], background); + } + textColor = new ColorStateList(textColor.getStates().clone(), + newColors); + resultSpan = new TextAppearanceSpan( + originalSpan.getFamily(), + originalSpan.getTextStyle(), + originalSpan.getTextSize(), + textColor, + originalSpan.getLinkTextColor()); + if (fullLength) { + outResultColor[0] = new ColorStateList( + textColor.getStates().clone(), newColors); + } + } + } else if (resultSpan instanceof ForegroundColorSpan) { + ForegroundColorSpan originalSpan = (ForegroundColorSpan) resultSpan; + int foregroundColor = originalSpan.getForegroundColor(); + foregroundColor = NotificationColorUtil.ensureLargeTextContrast( + foregroundColor, background); + resultSpan = new ForegroundColorSpan(foregroundColor); + if (fullLength) { + outResultColor[0] = ColorStateList.valueOf(foregroundColor); + } + } else { + resultSpan = span; + } + + builder.setSpan(resultSpan, spanStart, spanEnd, ss.getSpanFlags(span)); + } + return builder; + } + return charSequence; + } + + /** * @return Whether we are currently building a notification from a legacy (an app that * doesn't create material notifications by itself) app. */ diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index c33288bd568d..d0d233ebe975 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -2788,6 +2788,18 @@ public class RemoteViews implements Parcelable, Filter { } /** + * @hide + * Equivalent to calling {@link android.widget.TextView#setTextColor(ColorStateList)}. + * + * @param viewId The id of the view whose text color should change + * @param colors the text colors to set + */ + public void setTextColor(int viewId, @ColorInt ColorStateList colors) { + addAction(new ReflectionAction(viewId, "setTextColor", ReflectionAction.COLOR_STATE_LIST, + colors)); + } + + /** * Equivalent to calling {@link android.widget.AbsListView#setRemoteViewsAdapter(Intent)}. * * @param appWidgetId The id of the app widget which contains the specified view. (This diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 5cbd2841b57a..d3cb7425fe35 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -3255,6 +3255,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @attr ref android.R.styleable#TextView_textColor */ + @android.view.RemotableViewMethod public void setTextColor(ColorStateList colors) { if (colors == null) { throw new NullPointerException(); diff --git a/core/java/com/android/internal/util/NotificationColorUtil.java b/core/java/com/android/internal/util/NotificationColorUtil.java index 77452ca3a4dc..4748e6fb19ff 100644 --- a/core/java/com/android/internal/util/NotificationColorUtil.java +++ b/core/java/com/android/internal/util/NotificationColorUtil.java @@ -271,7 +271,7 @@ public class NotificationColorUtil { * Finds a text color with sufficient contrast over bg that has the same hue as the original * color, assuming it is for large text. */ - private static int ensureLargeTextContrast(int color, int bg) { + public static int ensureLargeTextContrast(int color, int bg) { return findContrastColor(color, bg, true, 3); } diff --git a/core/res/res/drawable/notification_material_action_background_emphasized.xml b/core/res/res/drawable/notification_material_action_background_emphasized.xml deleted file mode 100644 index b7153ba620e3..000000000000 --- a/core/res/res/drawable/notification_material_action_background_emphasized.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - ~ Copyright (C) 2016 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 - --> - -<ripple xmlns:android="http://schemas.android.com/apk/res/android" - android:color="@color/ripple_material_dark"> - <item android:id="@id/mask"> - <color android:color="@color/white" /> - </item> -</ripple> - diff --git a/core/res/res/layout/notification_material_action_emphasized.xml b/core/res/res/layout/notification_material_action_emphasized.xml index 992e43ede404..1e364cce3f4f 100644 --- a/core/res/res/layout/notification_material_action_emphasized.xml +++ b/core/res/res/layout/notification_material_action_emphasized.xml @@ -26,9 +26,9 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" - android:textColor="#ffffffff" + android:textColor="@color/notification_default_color" android:singleLine="true" android:ellipsize="end" - android:background="@drawable/notification_material_action_background_emphasized" + android:background="@drawable/notification_material_action_background" /> </FrameLayout> diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml index 1843475a0d09..de86cefb5bc7 100644 --- a/core/res/res/values/colors.xml +++ b/core/res/res/values/colors.xml @@ -140,6 +140,7 @@ <color name="notification_progress_background_color">@color/secondary_text_material_light</color> <color name="notification_action_list">#ffeeeeee</color> + <color name="notification_action_list_dark">#ffe0e0e0</color> <!-- Keyguard colors --> <color name="keyguard_avatar_frame_color">#ffffffff</color> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 38749f6e2cfa..516aa18f8651 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2558,6 +2558,7 @@ <java-symbol type="color" name="notification_action_list" /> <java-symbol type="color" name="notification_material_background_color" /> + <java-symbol type="color" name="notification_action_list_dark" /> <!-- Resolver target actions --> <java-symbol type="array" name="resolver_target_actions_pin" /> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java index 42c9a126ca14..9afb3846b028 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java @@ -137,11 +137,13 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView private float mNormalBackgroundVisibilityAmount; private ValueAnimator mFadeInFromDarkAnimator; + private float mDimmedBackgroundFadeInAmount = -1; private ValueAnimator.AnimatorUpdateListener mBackgroundVisibilityUpdater = new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { setNormalBackgroundVisibilityAmount(mBackgroundNormal.getAlpha()); + mDimmedBackgroundFadeInAmount = mBackgroundDimmed.getAlpha(); } }; private AnimatorListenerAdapter mFadeInEndListener = new AnimatorListenerAdapter() { @@ -149,6 +151,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); mFadeInFromDarkAnimator = null; + mDimmedBackgroundFadeInAmount = -1; updateBackground(); } }; @@ -597,7 +600,10 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView } protected void updateBackgroundAlpha(float transformationAmount) { - mBgAlpha = isChildInGroup() && mDimmed ? transformationAmount : 1f; + mBgAlpha = isChildInGroup() && mDimmed ? transformationAmount : 1f; + if (mDimmedBackgroundFadeInAmount != -1) { + mBgAlpha *= mDimmedBackgroundFadeInAmount; + } mBackgroundDimmed.setAlpha(mBgAlpha); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java index 5f6d958ed83e..58d402bb7432 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java @@ -1122,7 +1122,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { mPrivateLayout.setUserExpanding(userLocked); if (mIsSummaryWithChildren) { mChildrenContainer.setUserLocked(userLocked); - if (userLocked || (!userLocked && !isGroupExpanded())) { + if (userLocked || !isGroupExpanded()) { updateBackgroundForGroupState(); } } |