Quelles sont les façons de générer par programmation des jeux de couleurs Material Design?
J'essaie de créer une palette de couleurs de Conception de matériaux qui modifie la luminosité / luminosité par pourcentage avec un hex de couleur arbitraire. En ce qui concerne la mise en œuvre, j'ai constaté qu'il existe des hexadécimaux de couleur que je ne peux pas générer et affiche une exception de couleur inconnue. Voulez-vous me dire quelles sont les alternatives ou les précautions techniques pour générer cet ensemble de couleurs?
Ce qui suit est mon code
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);
}
}
Code pour tester
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));
2 answers
Problème d'Origine
Votre code a une erreur de travail avec le format de couleur.
Remplacez la dernière ligne de hslToColor()
comme indiqué ci-dessous et vous le ferez fonctionner sans erreurs:
public static String hslToColor(int alpha, float hue, float saturation, float lightness) {
...
// !!! ERROR WAS ON THE LAST LINE:
return String.format("#%08x", resultColorInt).toUpperCase();
}
Je l'ai testé - ça marche - parce que ça fait 2 choses supplémentaires:
1) Format valeur à 8 chiffres
2) Ajoute "#" préfixe
Deuxième problème possible dans votre code
La valeur alpha peut avoir des valeurs de 0 (transparent) à 255 (opaque). Si vous voulez avoir une image opaque, vous devez passer 255 (0xFF).
Maintenant, vous transmettez 1
et je pense que c'est une erreur - parce que c'est presque transparent.
Donc, pour avoir une couleur opaque remplacer la ligne
String baseColor = hslToColor(1 ,baseColorHSL[0] , baseColorHSL[1] , (float)0.5);
Avec
String baseColor = hslToColor(0xFF ,baseColorHSL[0] , baseColorHSL[1] , (float)0.5);
Annexe
Si l'on a besoin d'obtenir un ensemble de couleurs - un peu de créativité doit être appliquée.
Pour créer une teinte de la palette, vous devez changer dans une boucle a) saturation ou b) légèreté ou c) à la fois de ils.
Voici un exemple d'implémentation qui renvoie la palette en fonction du changement de luminosité de 0,4 à 0,6 (non inclus) en 10 étapes.
"Expérimentale" signifie que vous devriez trouver des valeurs pour vous-même.
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;
}
Le problème est dans les lignes suivantes:
int resultColorInt = Color.HSVToColor(alpha, new float[] { h, s, v });
return Integer.toHexString(resultColorInt).toUpperCase();
Lorsque la valeur alpha est inférieure à 16 (0xF0) , elle n'occupera qu'un seul caractère dans la chaîne:
// 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
Vous devez compenser les alphas 1-char ou 0-char (dans la plage 0-15) en ajoutant 0 au début de la chaîne résultante:
// 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;
Cependant, la meilleure chose serait d'éviter complètement les chaînes. Utilisez plutôt ints - ils contiennent les mêmes données avec de meilleures performances. Pour votre commodité, dans le débogueur, vous pouvez changer ints pour être affiché en hexadécimal, au lieu de DEC (dans Android Studio: faites un clic droit dans la vue Variables, Afficher sous -> HEXADÉCIMAL).