Як створити ColorStateList програмно?


158

Я намагаюся створити ColorStateListпрограмно, використовуючи це:

ColorStateList stateList = new ColorStateList(states, colors); 

Але я не впевнений, які два параметри.

Відповідно до документації:

public ColorStateList (int[][] states, int[] colors) 

Додано в рівень 1 API

Створює ColorStateList, який повертає вказане відображення зі станів у кольори.

Чи можете мені хтось пояснити, як це створити?

Яке значення двовимірного масиву для станів?

Відповіді:


343

Дивіться http://developer.android.com/reference/android/R.attr.html#state_above_anchor для переліку доступних станів.

Якщо ви хочете встановити кольори для вимкнених, нефокусованих, неконтрольованих станів тощо, просто заперечте стани:

int[][] states = new int[][] {
    new int[] { android.R.attr.state_enabled}, // enabled
    new int[] {-android.R.attr.state_enabled}, // disabled
    new int[] {-android.R.attr.state_checked}, // unchecked
    new int[] { android.R.attr.state_pressed}  // pressed
};

int[] colors = new int[] {
    Color.BLACK,
    Color.RED,
    Color.GREEN,
    Color.BLUE
};

ColorStateList myList = new ColorStateList(states, colors);

45
Дякуємо за інформацію про "протилежні" держави!
БВБ

Це можна використовувати для зміни кольору файлу з бібліотеки дизайну.
Tapirboy

5
ПОПЕРЕДЖЕННЯ. Дивіться відповідь Роджера Алієна (і його перший коментар), щоб зрозуміти, що порядок штатів тут поганий: оскільки "увімкнено" по-перше, він буде заміняти інші стани, які зазвичай виникають під час увімкнення кнопки. Краще поставити "включений" останнім. (Або замість "увімкнено", пустий / за замовчуванням останній елемент.)
ToolmakerSteve

2
Основний список станів для кнопки , яка зберігає стан (НЕ тумблер / CheckBox) може бути {pressed}, {focused}, {-enabled}, {}. Для перемикання це може бути {checked, pressed}, {pressed}, {checked, focused}, {focused}, {checked}, {-enabled}, {}. Або перемикач , який ігнорує фокус: {checked, pressed}, {pressed}, {checked}, {-enabled}, {}.
ToolmakerSteve

Якщо хтось спробує будь-яке з цих рішень, зверніть увагу на порядок таких станів, як у selector.xml!
Антон Маков

75

Перший вимір - це масив наборів станів, другий - сам стан. Масив кольорів перераховує кольори для кожного набору відповідних станів, тому довжина масиву кольорів повинна відповідати першому виміру масиву станів (або він руйнується, коли стан "використовується"). Ось і приклад:

ColorStateList myColorStateList = new ColorStateList(
                        new int[][]{
                                new int[]{android.R.attr.state_pressed}, //1
                                new int[]{android.R.attr.state_focused}, //2
                                new int[]{android.R.attr.state_focused, android.R.attr.state_pressed} //3
                        },
                        new int[] {
                            Color.RED, //1
                            Color.GREEN, //2
                            Color.BLUE //3
                        }
                    );

сподіваюся, що це допомагає.

Приклад редагування: список стану кольорів у форматі XML:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:color="@color/white"/>
    <item android:color="@color/black"/>
</selector>

виглядав би так

ColorStateList myColorStateList = new ColorStateList(
        new int[][]{
                new int[]{android.R.attr.state_pressed},
                new int[]{}
        },
        new int[] {
                context.getResources().getColor(R.color.white),
                context.getResources().getColor(R.color.black)
        }
);

Чи можете ви сказати, як представити нижче xml "<селектор xmlns: android =" schemas.android.com/apk/res/android "> <item android: state_press =" true "android: color =" @ color / white "/ > <item android: color = "@ color / black" /> </selector> "за допомогою colorstatelist.
Satish

@SatishKumar перевірити мою редагування, я не перевіряв її.
Su-Au Hwang

3
Варто сказати, що, щоб вказати помилковий стан, ви можете заперечити його значення, тому якщо ви хочете вказати колір, коли він не натискається, слід використовувати: new int [] {- ​​android.R.attr.state_press}
tinsukE

1
Щоб додати те, що сказав @tinsukE: Однак, щоб випадково не придушити елемент пізніше у списку, для більшості держав не має сенсу ставити заперечення - натомість обробляти всі "інші" можливості за допомогою елемента за замовчуванням (порожній) new int[]{}остання - як показано в заключному блоці коду цієї відповіді. Єдине заперечне значення, яке я зазвичай використовую, - "увімкнено". Інший приклад, якщо ви хочете три різних кольори: «зосереджені + натиснута», «зосереджені + не було натиснуто», «натиснув + не сфокусовані», ви можете просто покласти {focused, pressed}, {focused}, {pressed}. Буде використано перше "справжнє".
ToolmakerSteve

2
... Помилка ви можете зробити це , щоб мати ряд , як {pressed}, {-pressed}, {focused}, {-focused}. Проблема полягає в тому, що {pressed}і {-pressed}покрийте ВСІ можливості (кнопку натискають або не натискають), тому жодні кольори, перелічені пізніше, ніколи не будуть використані.!
ToolmakerSteve

64

Іноді цього буде достатньо:

int colorInt = getResources().getColor(R.color.ColorVerificaLunes);
ColorStateList csl = ColorStateList.valueOf(colorInt);

20

На жаль, жодне з рішень не працює для мене.

  1. Якщо ви спочатку не встановите натиснутий стан, воно не виявить.
  2. Якщо ви його встановите, вам потрібно визначити порожній стан, щоб додати колір за замовчуванням
ColorStateList themeColorStateList = new ColorStateList(
        new int[][]{
                new int[]{android.R.attr.state_pressed},
                new int[]{android.R.attr.state_enabled},
                new int[]{android.R.attr.state_focused, android.R.attr.state_pressed},
                new int[]{-android.R.attr.state_enabled},
                new int[]{} // this should be empty to make default color as we want
        },
        new int[]{
                pressedFontColor,
                defaultFontColor,
                pressedFontColor,
                disabledFontColor,
                defaultFontColor
        }
);

Це конструктор з вихідного коду:

/**
 * Creates a ColorStateList that returns the specified mapping from
 * states to colors.
 */
public ColorStateList(int[][] states, int[] colors) {
    mStateSpecs = states;
    mColors = colors;

    if (states.length > 0) {
        mDefaultColor = colors[0];

        for (int i = 0; i < states.length; i++) {
            if (states[i].length == 0) {
                mDefaultColor = colors[i];
            }
        }
    }
}

5
Так само, як сторонне позначення: Ви повинні ставитися до цього так, як інакше. Він вибирає перший стан, що відповідає дійсності. Отже, якщо у вас увімкнено state_enabled як перший стан, він буде обраний перед state_press - якщо тільки перегляд не вимкнено.
LeoFarage

FWIW, оскільки у вас останній елемент за замовчуванням, я не думаю, що перший "включений" елемент взагалі не приносить вам користі. Чому б не видалити його повністю?
ToolmakerSteve

18

Ось приклад, як створити ColorListпрограмно в Котліні:

val colorList = ColorStateList(
        arrayOf(
                intArrayOf(-android.R.attr.state_enabled),  // Disabled
                intArrayOf(android.R.attr.state_enabled)    // Enabled
        ),
        intArrayOf(
                Color.BLACK,     // The color for the Disabled state
                Color.RED        // The color for the Enabled state
        )
)

Також дивіться мою відповідь нижче щодо функції помічника Котліна.
arekolek

7

Відштовхуючись від відповіді Джонатана Елліса , у Котліні ви можете визначити функцію помічника, щоб зробити код трохи ідіоматичнішим і легшим для читання, тому ви можете написати це замість цього:

val colorList = colorStateListOf(
    intArrayOf(-android.R.attr.state_enabled) to Color.BLACK,
    intArrayOf(android.R.attr.state_enabled) to Color.RED
)

colorStateListOf можна реалізувати так:

fun colorStateListOf(vararg mapping: Pair<IntArray, Int>): ColorStateList {
    val (states, colors) = mapping.unzip()
    return ColorStateList(states.toTypedArray(), colors.toIntArray())
}

Я також маю:

fun colorStateListOf(@ColorInt color: Int): ColorStateList {
    return ColorStateList.valueOf(color)
}

Так що я можу викликати одне й те саме ім’я функції, незалежно від того, чи це селектор або один колір.


3

Мій клас будівельника для створення ColorStateList

private class ColorStateListBuilder {
    List<Integer> colors = new ArrayList<>();
    List<int[]> states = new ArrayList<>();

    public ColorStateListBuilder addState(int[] state, int color) {
        states.add(state);
        colors.add(color);
        return this;
    }

    public ColorStateList build() {
        return new ColorStateList(convertToTwoDimensionalIntArray(states),
                convertToIntArray(colors));
    }

    private int[][] convertToTwoDimensionalIntArray(List<int[]> integers) {
        int[][] result = new int[integers.size()][1];
        Iterator<int[]> iterator = integers.iterator();
        for (int i = 0; iterator.hasNext(); i++) {
            result[i] = iterator.next();
        }
        return result;
    }

    private int[] convertToIntArray(List<Integer> integers) {
        int[] result = new int[integers.size()];
        Iterator<Integer> iterator = integers.iterator();
        for (int i = 0; iterator.hasNext(); i++) {
            result[i] = iterator.next();
        }
        return result;
    }
}

Приклад використання

ColorStateListBuilder builder = new ColorStateListBuilder();
builder.addState(new int[] { android.R.attr.state_pressed }, ContextCompat.getColor(this, colorRes))
       .addState(new int[] { android.R.attr.state_selected }, Color.GREEN)
       .addState(..., some color);

if(// some condition){
      builder.addState(..., some color);
}
builder.addState(new int[] {}, colorNormal); // must add default state at last of all state

ColorStateList stateList = builder.build(); // ColorStateList created here

// textView.setTextColor(stateList);

2

якщо ви використовуєте ресурс Colors.xml

int[] colors = new int[] {
                getResources().getColor(R.color.ColorVerificaLunes),
                getResources().getColor(R.color.ColorVerificaMartes),
                getResources().getColor(R.color.ColorVerificaMiercoles),
                getResources().getColor(R.color.ColorVerificaJueves),
                getResources().getColor(R.color.ColorVerificaViernes)

        };

ColorStateList csl = new ColorStateList(new int[][]{new int[0]}, new int[]{colors[0]}); 

    example.setBackgroundTintList(csl);

2
як getResources()застаріле, воно зараз ContextCompat.getColor(this,R.color.colorname);або ContextCompat.getColor(getActivity(),R.color.colorname);для використання у Фрагменті
iBobb

Для уточнення для інших читачів, new int[0](як елемент у списку першого параметра) є масив нульової довжини і являє собою встановлення кольору за замовчуванням. Тут це єдиний елемент, а це означає, що відтінок наноситься на всі стани кнопки. Це рівнозначно тому, що new int[]{}видно у відповіді Роджера Алієна.
ToolmakerSteve
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.