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?

entrez la description de l'image iciCe 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));
Author: Peter O., 2015-01-18

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;
}
 5
Author: sberezin, 2015-10-05 06:51:19

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).

 0
Author: stealth, 2015-01-28 12:01:04