diff options
| author | 2021-03-24 12:36:33 -0700 | |
|---|---|---|
| committer | 2021-03-25 12:55:51 -0700 | |
| commit | 7a597bb5a03d1728c5a8840b4139ba6dfaa674e8 (patch) | |
| tree | 5c0041df3ebb944c893e04101b6c5a6f1906dbda | |
| parent | d99447b68f69b80dfbc3572e5f9c198d9128b261 (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.txt | 2 | ||||
| -rw-r--r-- | core/java/android/content/res/ColorStateList.java | 55 | ||||
| -rw-r--r-- | core/res/res/values/attrs.xml | 4 | ||||
| -rw-r--r-- | core/res/res/values/public.xml | 1 |
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" /> * </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> + * <item android:state_enabled="false" + * android:color="?android:attr/colorAccent" + * android:lStar="50" /> + * </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"> |