Каковы способы программного создания наборов цветов Material Design?

Я пытаюсь создать цветовую палитру Material Design, которая меняет яркость/светимость в процентах с помощью произвольного цветового гекса. Когда дело доходит до реализации, я обнаружил, что есть какой-то гексагон цвета, который я не могу создать, и показывает исключение цвета неизвестно. Не могли бы вы рассказать мне, какие альтернативы или технические меры для создания этого набора цветов?

enter image description here Ниже приведен мой код

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

Ответ 1

Исходная проблема

В вашем коде есть ошибка, работающая с цветовым форматом. Замените последнюю строку 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();
}

Я тестировал его - он работает - потому что он делает две дополнительные вещи:
1) Форматирует значение для 8 цифр
2) Добавляет префикс " #"

Возможная проблема SECOND в вашем коде

Значение альфа может иметь значения от 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). Вот пример реализации, который возвращает палитру на основе изменения легкости от 0,4 до 0,6 (не включительно) за 10 шагов.
"Экспериментальный" означает, что вы должны найти значения для себя.

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;
}

Ответ 2

Проблема заключается в следующих строках:

int resultColorInt =  Color.HSVToColor(alpha, new float[] { h, s, v });
return Integer.toHexString(resultColorInt).toUpperCase();

Когда значение альфа меньше 16 (0xF0), оно будет занимать только одну строку char в строке:

// 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

Вам нужно компенсировать 1- char или 0- char alphas (в диапазоне 0-15), добавив 0 в начале результирующей строки:

// 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;

Однако лучше всего было бы избежать струн вообще. Вместо этого используйте ints - они содержат одни и те же данные с лучшей производительностью. Для вашего удобства в отладчике вы можете изменить ints для отображения на HEX вместо DEC (в Android Studio: щелкните правой кнопкой мыши в представлении Variables, View as → HEX).