summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Lucas Dupin <dupin@google.com> 2021-03-24 12:36:33 -0700
committer Lucas Dupin <dupin@google.com> 2021-03-25 12:55:51 -0700
commit7a597bb5a03d1728c5a8840b4139ba6dfaa674e8 (patch)
tree5c0041df3ebb944c893e04101b6c5a6f1906dbda
parentd99447b68f69b80dfbc3572e5f9c198d9128b261 (diff)
Add luma capabilities to ColorStateList
It's now possible to define an lStar attribute. This attribute will modify the base color in a way that its chroma will be conserved, but perceptive luminance will change. Fixes: 183609373 Test: atest ColorStateListTest Change-Id: I341a0a532bd9c030e8f52185bacda0db55486216
-rw-r--r--core/api/current.txt2
-rw-r--r--core/java/android/content/res/ColorStateList.java55
-rw-r--r--core/res/res/values/attrs.xml4
-rw-r--r--core/res/res/values/public.xml1
4 files changed, 57 insertions, 5 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index f3b9b822ceda..2a71ff72e8a8 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -866,6 +866,7 @@ package android {
field public static final int keycode = 16842949; // 0x10100c5
field public static final int killAfterRestore = 16843420; // 0x101029c
field public static final int knownCerts = 16844330; // 0x101062a
+ field public static final int lStar = 16844359; // 0x1010647
field public static final int label = 16842753; // 0x1010001
field public static final int labelFor = 16843718; // 0x10103c6
field @Deprecated public static final int labelTextSize = 16843317; // 0x1010235
@@ -13158,6 +13159,7 @@ package android.content.res {
method public boolean isStateful();
method @NonNull public static android.content.res.ColorStateList valueOf(@ColorInt int);
method @NonNull public android.content.res.ColorStateList withAlpha(int);
+ method @NonNull public android.content.res.ColorStateList withLStar(float);
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.content.res.ColorStateList> CREATOR;
}
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index 921c63025a57..cdd8265ad5cd 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -34,6 +34,7 @@ import android.util.StateSet;
import android.util.Xml;
import com.android.internal.R;
+import com.android.internal.graphics.ColorUtils;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.GrowingArrayUtils;
@@ -112,6 +113,18 @@ import java.util.Arrays;
* android:color="?android:attr/colorAccent"
* android:alpha="0.5" /&gt;
* </pre>
+ * <p>
+ * Starting with API 31, items may optionally define an {@link android.R.attr#lStar android:lStar}
+ * attribute to modify the base color's perceptual luminance. This attribute takes a either
+ * floating-point value between 0 and 100 or a theme attribute that resolves as such. The item's
+ * overall color is calculated by converting the base color to an accessibility friendly color space
+ * and setting its L* to the value specified on the {@code lStar} attribute. For
+ * example, the following item represents the theme's accent color at 50% perpectual luminosity:
+ * <pre>
+ * &lt;item android:state_enabled="false"
+ * android:color="?android:attr/colorAccent"
+ * android:lStar="50" /&gt;
+ * </pre>
*
* <a name="DeveloperGuide"></a>
* <h3>Developer guide</h3>
@@ -122,6 +135,7 @@ import java.util.Arrays;
*
* @attr ref android.R.styleable#ColorStateListItem_alpha
* @attr ref android.R.styleable#ColorStateListItem_color
+ * @attr ref android.R.styleable#ColorStateListItem_lStar
*/
public class ColorStateList extends ComplexColor implements Parcelable {
private static final String TAG = "ColorStateList";
@@ -301,6 +315,24 @@ public class ColorStateList extends ComplexColor implements Parcelable {
}
/**
+ * Creates a new ColorStateList that has the same states and colors as this
+ * one but where each color has the specified perceived luminosity value (0-100).
+ *
+ * @param lStar Target perceptual luminance (0-100).
+ * @return A new color state list.
+ */
+ @NonNull
+ public ColorStateList withLStar(float lStar) {
+ final int[] colors = new int[mColors.length];
+ final int len = colors.length;
+ for (int i = 0; i < len; i++) {
+ colors[i] = modulateColor(mColors[i], 1.0f /* alphaMod */, lStar);
+ }
+
+ return new ColorStateList(mStateSpecs, colors);
+ }
+
+ /**
* Fill in this object based on the contents of an XML "selector" element.
*/
private void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
@@ -332,6 +364,7 @@ public class ColorStateList extends ComplexColor implements Parcelable {
final int[] themeAttrs = a.extractThemeAttrs();
final int baseColor = a.getColor(R.styleable.ColorStateListItem_color, Color.MAGENTA);
final float alphaMod = a.getFloat(R.styleable.ColorStateListItem_alpha, 1.0f);
+ final float lStar = a.getFloat(R.styleable.ColorStateListItem_lStar, -1.0f);
changingConfigurations |= a.getChangingConfigurations();
@@ -346,6 +379,7 @@ public class ColorStateList extends ComplexColor implements Parcelable {
switch (stateResId) {
case R.attr.color:
case R.attr.alpha:
+ case R.attr.lStar:
// Recognized attribute, ignore.
break;
default:
@@ -355,10 +389,11 @@ public class ColorStateList extends ComplexColor implements Parcelable {
}
stateSpec = StateSet.trimStateSet(stateSpec, j);
- // Apply alpha modulation. If we couldn't resolve the color or
+ // Apply alpha and luma modulation. If we couldn't resolve the color or
// alpha yet, the default values leave us enough information to
// modulate again during applyTheme().
- final int color = modulateColorAlpha(baseColor, alphaMod);
+ final int color = modulateColor(baseColor, alphaMod, lStar);
+
if (listSize == 0 || stateSpec.length == 0) {
defaultColor = color;
}
@@ -455,7 +490,9 @@ public class ColorStateList extends ComplexColor implements Parcelable {
R.styleable.ColorStateListItem_color, mColors[i]);
final float alphaMod = a.getFloat(
R.styleable.ColorStateListItem_alpha, defaultAlphaMod);
- mColors[i] = modulateColorAlpha(baseColor, alphaMod);
+ final float lStar = a.getFloat(
+ R.styleable.ColorStateListItem_lStar, -1.0f);
+ mColors[i] = modulateColor(baseColor, alphaMod, lStar);
// Account for any configuration changes.
mChangingConfigurations |= a.getChangingConfigurations();
@@ -505,13 +542,21 @@ public class ColorStateList extends ComplexColor implements Parcelable {
return super.getChangingConfigurations() | mChangingConfigurations;
}
- private int modulateColorAlpha(int baseColor, float alphaMod) {
- if (alphaMod == 1.0f) {
+ private int modulateColor(int baseColor, float alphaMod, float lStar) {
+ final boolean validLStar = lStar >= 0.0f && lStar <= 100.0f;
+ if (alphaMod == 1.0f && !validLStar) {
return baseColor;
}
final int baseAlpha = Color.alpha(baseColor);
final int alpha = MathUtils.constrain((int) (baseAlpha * alphaMod + 0.5f), 0, 255);
+
+ if (validLStar) {
+ final double[] labColor = new double[3];
+ ColorUtils.colorToLAB(baseColor, labColor);
+ baseColor = ColorUtils.LABToColor(lStar, labColor[1], labColor[2]);
+ }
+
return (baseColor & 0xFFFFFF) | (alpha << 24);
}
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 4b15e01369be..74f8ff655165 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -6070,6 +6070,8 @@
<attr name="color" />
<!-- Alpha multiplier applied to the base color. -->
<attr name="alpha" />
+ <!-- Perceptual luminance applied to the base color. From 0 to 100. -->
+ <attr name="lStar" format="float" />
</declare-styleable>
<!-- Drawable used to render according to the animation scale. Esp. when it is 0 due to battery
@@ -9535,4 +9537,6 @@
<attr name="iconfactoryIconSize" format="dimension"/>
<attr name="iconfactoryBadgeSize" format="dimension"/>
+ <!-- Perceptual luminance of a color, in accessibility friendly color space. From 0 to 100. -->
+ <attr name="lStar" format="float"/>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index bc49818638bc..49039f9370dd 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3095,6 +3095,7 @@
<public name="requestOptimizedExternalStorageAccess" />
<!-- @hide @SystemApi -->
<public name="playHomeTransitionSound" />
+ <public name="lStar" />
</public-group>
<public-group type="drawable" first-id="0x010800b5">