Merge "Transforming all texts of decorated media custom views" into oc-mr1-dev

This commit is contained in:
Selim Cinek
2017-08-23 15:55:41 +00:00
committed by Android (Google) Code Review
3 changed files with 106 additions and 42 deletions

View File

@@ -60,7 +60,6 @@ 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;
@@ -3923,7 +3922,7 @@ public class Notification implements Parcelable
private CharSequence processTextSpans(CharSequence text) {
if (hasForegroundColor()) {
return clearColorSpans(text);
return NotificationColorUtil.clearColorSpans(text);
}
return text;
}
@@ -4683,7 +4682,7 @@ public class Notification implements Parcelable
CharSequence title = action.title;
ColorStateList[] outResultColor = null;
if (isLegacy()) {
title = clearColorSpans(title);
title = NotificationColorUtil.clearColorSpans(title);
} else {
outResultColor = new ColorStateList[1];
title = ensureColorSpanContrast(title, bgColor, outResultColor);
@@ -4710,45 +4709,6 @@ public class Notification implements Parcelable
return button;
}
/**
* 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.
@@ -7075,6 +7035,7 @@ public class Notification implements Parcelable
// Need to clone customContent before adding, because otherwise it can no longer be
// parceled independently of remoteViews.
customContent = customContent.clone();
customContent.overrideTextColors(mBuilder.getPrimaryTextColor());
remoteViews.removeAllViews(id);
remoteViews.addView(id, customContent);
remoteViews.setReapplyDisallowed();

View File

@@ -64,6 +64,7 @@ import android.view.ViewStub;
import android.widget.AdapterView.OnItemClickListener;
import com.android.internal.R;
import com.android.internal.util.NotificationColorUtil;
import com.android.internal.util.Preconditions;
import libcore.util.Objects;
@@ -75,6 +76,7 @@ import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Stack;
import java.util.concurrent.Executor;
/**
@@ -118,6 +120,7 @@ public class RemoteViews implements Parcelable, Filter {
private static final int TEXT_VIEW_DRAWABLE_COLOR_FILTER_ACTION_TAG = 17;
private static final int SET_REMOTE_INPUTS_ACTION_TAG = 18;
private static final int LAYOUT_PARAM_ACTION_TAG = 19;
private static final int OVERRIDE_TEXT_COLORS_TAG = 20;
/**
* Application that hosts the remote views.
@@ -220,6 +223,17 @@ public class RemoteViews implements Parcelable, Filter {
}
}
/**
* Override all text colors in this layout and replace them by the given text color.
*
* @param textColor The color to use.
*
* @hide
*/
public void overrideTextColors(int textColor) {
addAction(new OverrideTextColorsAction(textColor));
}
/**
* Set that it is disallowed to reapply another remoteview with the same layout as this view.
* This should be done if an action is destroying the view tree of the base layout.
@@ -2248,6 +2262,52 @@ public class RemoteViews implements Parcelable, Filter {
final Parcelable[] remoteInputs;
}
/**
* Helper action to override all textViewColors
*/
private class OverrideTextColorsAction extends Action {
private final int textColor;
public OverrideTextColorsAction(int textColor) {
this.textColor = textColor;
}
public OverrideTextColorsAction(Parcel parcel) {
textColor = parcel.readInt();
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(OVERRIDE_TEXT_COLORS_TAG);
dest.writeInt(textColor);
}
@Override
public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
// Let's traverse the viewtree and override all textColors!
Stack<View> viewsToProcess = new Stack<>();
viewsToProcess.add(root);
while (!viewsToProcess.isEmpty()) {
View v = viewsToProcess.pop();
if (v instanceof TextView) {
TextView textView = (TextView) v;
textView.setText(NotificationColorUtil.clearColorSpans(textView.getText()));
textView.setTextColor(textColor);
}
if (v instanceof ViewGroup) {
ViewGroup viewGroup = (ViewGroup) v;
for (int i = 0; i < viewGroup.getChildCount(); i++) {
viewsToProcess.push(viewGroup.getChildAt(i));
}
}
}
}
public String getActionName() {
return "OverrideTextColorsAction";
}
}
/**
* Simple class used to keep track of memory usage in a RemoteViews.
*
@@ -2443,6 +2503,9 @@ public class RemoteViews implements Parcelable, Filter {
case LAYOUT_PARAM_ACTION_TAG:
mActions.add(new LayoutParamAction(parcel));
break;
case OVERRIDE_TEXT_COLORS_TAG:
mActions.add(new OverrideTextColorsAction(parcel));
break;
default:
throw new ActionException("Tag " + tag + " not found");
}

View File

@@ -33,6 +33,7 @@ import android.graphics.drawable.Icon;
import android.graphics.drawable.VectorDrawable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.BackgroundColorSpan;
import android.text.style.CharacterStyle;
import android.text.style.ForegroundColorSpan;
import android.text.style.TextAppearanceSpan;
@@ -240,6 +241,45 @@ public class NotificationColorUtil {
return span;
}
/**
* Clears all color spans of a text
* @param charSequence the input text
* @return the same text but without color spans
*/
public static 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;
}
private int processColor(int color) {
return Color.argb(Color.alpha(color),
255 - Color.red(color),