以编程方式生成 Material 设计颜色集的方法有哪些?
What are the ways to programmatically generate Material Design color sets?
我正在尝试创建一个 Material 设计的调色板,该调色板使用任意十六进制颜色按百分比更改亮度/亮度。当涉及到实现时,我发现有些颜色十六进制我无法生成并显示颜色未知异常。请告诉我生成这组颜色的替代方法或技术预防措施是什么?
以下是我的代码
package com.example.dino.util;
import android.content.Context;
import android.graphics.Color;
import java.util.ArrayList;
/**
* Created by larrylo on 18/1/15.
*/
public class ColorUtils {
public Context context;
public static float[] colorToHsl(String hexColor) {
int color = Color.parseColor(hexColor);
float r = ((0x00ff0000 & color) >> 16) / 255.0F;
float g = ((0x0000ff00 & color) >> 8) / 255.0F;
float b = ((0x000000ff & color)) / 255.0F;
float max = Math.max(Math.max(r, g), b);
float min = Math.min(Math.min(r, g), b);
float c = max - min;
float hTemp = 0.0F;
if (c == 0) {
hTemp = 0;
} else if (max == r) {
hTemp = (float) (g - b) / c;
if (hTemp < 0)
hTemp += 6.0F;
} else if (max == g) {
hTemp = (float) (b - r) / c + 2.0F;
} else if (max == b) {
hTemp = (float) (r - g) / c + 4.0F;
}
float h = 60.0F * hTemp;
float l = (max + min) * 0.5F;
float s;
if (c == 0) {
s = 0.0F;
} else {
s = c / (1 - Math.abs(2.0F * l - 1.0F));
}
float [] hsl = {h , s , l } ;
return hsl;
}
public static String hslToColor(int alpha, float hue, float saturation, float lightness) {
float hh = hue;
float ss = saturation;
float ll = lightness;
float h, s, v;
h = hh;
ll *= 2;
ss *= (ll <= 1) ? Ll : 2 - ll;
v = (ll + ss) / 2;
s = ((ll + ss) != 0) ? (2 * ss) / (ll + ss) : 0;
int resultColorInt = Color.HSVToColor(alpha, new float[] { h, s, v });
return Integer.toHexString(resultColorInt).toUpperCase();
}
public static ArrayList<String> returnMaterialDesignColorSet (String colorHex){
ArrayList<String> resultList = new ArrayList<String>();
float [] baseColorHSL = colorToHsl(colorHex);
double randomMid = randomWithRange(0.48 , 0.52);
String baseColor = hslToColor(1 ,baseColorHSL[0] , baseColorHSL[1] , (float)0.5);
resultList.add(baseColor);
return resultList;
}
public static double randomWithRange(double min, double max)
{
double range = Math.abs(max - min);
return (Math.random() * range) + (min <= max ? Min : max);
}
public static int colorInt (String hex){
return Color.parseColor(hex);
}
}
测试代码
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);
double max = 0.52;
double min = 0.48;
double range = Math.abs(max - min);
double value = (Math.random() * range) + (min <= max ? Min : max);
float result = (float)value;
System.out.println(result);
String test = "#973f5c";
String test2 = ColorUtils.returnMaterialDesignColorSet(test).get(0);
int colorInt = ColorUtils.colorInt(test2);
actionBar .setBackgroundDrawable(new ColorDrawable(colorInt));
问题出在以下几行:
int resultColorInt = Color.HSVToColor(alpha, new float[] { h, s, v });
return Integer.toHexString(resultColorInt).toUpperCase();
当alpha值小于16(0xF0)时,只占字符串中的一个字符:
// 1-char alpha
int resultColorInt = Color.HSVToColor(1, new float[]{340, 0.7f, 0.5f});
String result = Integer.toHexString(resultColorInt).toUpperCase();
// result == "1802644" - 7 chars, which is invalid color format
您需要通过在结果字符串的开头附加 0 来补偿 1 个字符或 0 个字符的字母(在 0-15 范围内):
// not the best code, but works
while (result.length() < 8) {
result = "0" + result;
}
// don't forget # to make it a legal color
result = "#" + result;
return result;
但是,最好的办法是完全避免使用字符串。改用整数——它们包含相同的数据,但性能更好。为了您的方便,在调试器中,您可以将整数更改为以 HEX 显示,而不是 DEC(在 Android Studio 中:右键单击变量视图,查看为 -> HEX)。
原始问题
您的代码在使用颜色格式时出错。
如下所示替换 hslToColor()
的最后一行,您将使其 运行 没有错误:
public static String hslToColor(int alpha, float hue, float saturation, float lightness) {
...
// !!! ERROR WAS ON THE LAST LINE:
return String.format("#%08x", resultColorInt).toUpperCase();
}
我已经测试过了 - 它可以工作 - 因为它还有 2 个额外的功能:
1) 将值格式化为 8 位
2) 添加“#”前缀
您的代码中可能存在第二个问题
alpha 值可以具有从 0(透明)到 255(不透明)的值。如果你想要不透明的图像,你应该传递 255 (0xFF)。
现在你传递 1
和 我认为这是一个错误 - 因为它几乎是透明的。
所以要用不透明的颜色替换线
String baseColor = hslToColor(1 ,baseColorHSL[0] , baseColorHSL[1] , (float)0.5);
和
String baseColor = hslToColor(0xFF ,baseColorHSL[0] , baseColorHSL[1] , (float)0.5);
附件
如果需要获得一组颜色 - 应该应用一点创意。
要创建色调调色板,您必须循环更改 a) 饱和度或 b) 亮度或 c)他们两个。
这是一个实现示例,returns 基于亮度的调色板在 10 个步骤中从 0.4 变为 0.6(不包含)。
"Experimental"意味着你应该为自己找到价值。
public static ArrayList<String> returnMaterialDesignColorSet(String baseColorHex, int colorCount) {
ArrayList<String> resultList = new ArrayList<String>();
float [] baseColorHSL = colorToHsl(baseColorHex);
float lght=0.4;// initial lightness value (experimental)
float lStep=(0.6 - lght) / colorCount; // step to go up to 0.6 lightness (experimental)
for (int i = 0; i < colorCount; i++) {
String baseColor = hslToColor(1 ,baseColorHSL[0] , baseColorHSL[1] , lght);
resultList.add(baseColor);
lght += lStep;
}
return resultList;
}
我正在尝试创建一个 Material 设计的调色板,该调色板使用任意十六进制颜色按百分比更改亮度/亮度。当涉及到实现时,我发现有些颜色十六进制我无法生成并显示颜色未知异常。请告诉我生成这组颜色的替代方法或技术预防措施是什么?
package com.example.dino.util;
import android.content.Context;
import android.graphics.Color;
import java.util.ArrayList;
/**
* Created by larrylo on 18/1/15.
*/
public class ColorUtils {
public Context context;
public static float[] colorToHsl(String hexColor) {
int color = Color.parseColor(hexColor);
float r = ((0x00ff0000 & color) >> 16) / 255.0F;
float g = ((0x0000ff00 & color) >> 8) / 255.0F;
float b = ((0x000000ff & color)) / 255.0F;
float max = Math.max(Math.max(r, g), b);
float min = Math.min(Math.min(r, g), b);
float c = max - min;
float hTemp = 0.0F;
if (c == 0) {
hTemp = 0;
} else if (max == r) {
hTemp = (float) (g - b) / c;
if (hTemp < 0)
hTemp += 6.0F;
} else if (max == g) {
hTemp = (float) (b - r) / c + 2.0F;
} else if (max == b) {
hTemp = (float) (r - g) / c + 4.0F;
}
float h = 60.0F * hTemp;
float l = (max + min) * 0.5F;
float s;
if (c == 0) {
s = 0.0F;
} else {
s = c / (1 - Math.abs(2.0F * l - 1.0F));
}
float [] hsl = {h , s , l } ;
return hsl;
}
public static String hslToColor(int alpha, float hue, float saturation, float lightness) {
float hh = hue;
float ss = saturation;
float ll = lightness;
float h, s, v;
h = hh;
ll *= 2;
ss *= (ll <= 1) ? Ll : 2 - ll;
v = (ll + ss) / 2;
s = ((ll + ss) != 0) ? (2 * ss) / (ll + ss) : 0;
int resultColorInt = Color.HSVToColor(alpha, new float[] { h, s, v });
return Integer.toHexString(resultColorInt).toUpperCase();
}
public static ArrayList<String> returnMaterialDesignColorSet (String colorHex){
ArrayList<String> resultList = new ArrayList<String>();
float [] baseColorHSL = colorToHsl(colorHex);
double randomMid = randomWithRange(0.48 , 0.52);
String baseColor = hslToColor(1 ,baseColorHSL[0] , baseColorHSL[1] , (float)0.5);
resultList.add(baseColor);
return resultList;
}
public static double randomWithRange(double min, double max)
{
double range = Math.abs(max - min);
return (Math.random() * range) + (min <= max ? Min : max);
}
public static int colorInt (String hex){
return Color.parseColor(hex);
}
}
测试代码
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);
double max = 0.52;
double min = 0.48;
double range = Math.abs(max - min);
double value = (Math.random() * range) + (min <= max ? Min : max);
float result = (float)value;
System.out.println(result);
String test = "#973f5c";
String test2 = ColorUtils.returnMaterialDesignColorSet(test).get(0);
int colorInt = ColorUtils.colorInt(test2);
actionBar .setBackgroundDrawable(new ColorDrawable(colorInt));
问题出在以下几行:
int resultColorInt = Color.HSVToColor(alpha, new float[] { h, s, v });
return Integer.toHexString(resultColorInt).toUpperCase();
当alpha值小于16(0xF0)时,只占字符串中的一个字符:
// 1-char alpha
int resultColorInt = Color.HSVToColor(1, new float[]{340, 0.7f, 0.5f});
String result = Integer.toHexString(resultColorInt).toUpperCase();
// result == "1802644" - 7 chars, which is invalid color format
您需要通过在结果字符串的开头附加 0 来补偿 1 个字符或 0 个字符的字母(在 0-15 范围内):
// not the best code, but works
while (result.length() < 8) {
result = "0" + result;
}
// don't forget # to make it a legal color
result = "#" + result;
return result;
但是,最好的办法是完全避免使用字符串。改用整数——它们包含相同的数据,但性能更好。为了您的方便,在调试器中,您可以将整数更改为以 HEX 显示,而不是 DEC(在 Android Studio 中:右键单击变量视图,查看为 -> HEX)。
原始问题
您的代码在使用颜色格式时出错。
如下所示替换 hslToColor()
的最后一行,您将使其 运行 没有错误:
public static String hslToColor(int alpha, float hue, float saturation, float lightness) {
...
// !!! ERROR WAS ON THE LAST LINE:
return String.format("#%08x", resultColorInt).toUpperCase();
}
我已经测试过了 - 它可以工作 - 因为它还有 2 个额外的功能:
1) 将值格式化为 8 位
2) 添加“#”前缀
您的代码中可能存在第二个问题
alpha 值可以具有从 0(透明)到 255(不透明)的值。如果你想要不透明的图像,你应该传递 255 (0xFF)。
现在你传递 1
和 我认为这是一个错误 - 因为它几乎是透明的。
所以要用不透明的颜色替换线
String baseColor = hslToColor(1 ,baseColorHSL[0] , baseColorHSL[1] , (float)0.5);
和
String baseColor = hslToColor(0xFF ,baseColorHSL[0] , baseColorHSL[1] , (float)0.5);
附件
如果需要获得一组颜色 - 应该应用一点创意。
要创建色调调色板,您必须循环更改 a) 饱和度或 b) 亮度或 c)他们两个。
这是一个实现示例,returns 基于亮度的调色板在 10 个步骤中从 0.4 变为 0.6(不包含)。
"Experimental"意味着你应该为自己找到价值。
public static ArrayList<String> returnMaterialDesignColorSet(String baseColorHex, int colorCount) {
ArrayList<String> resultList = new ArrayList<String>();
float [] baseColorHSL = colorToHsl(baseColorHex);
float lght=0.4;// initial lightness value (experimental)
float lStep=(0.6 - lght) / colorCount; // step to go up to 0.6 lightness (experimental)
for (int i = 0; i < colorCount; i++) {
String baseColor = hslToColor(1 ,baseColorHSL[0] , baseColorHSL[1] , lght);
resultList.add(baseColor);
lght += lStep;
}
return resultList;
}