Как создать ColorStateList программно?

Я пытаюсь создать ColorStateList программно, используя это:

ColorStateList stateList = new ColorStateList(states, colors); 

Но я не уверен, каковы два параметра.

В соответствии с документацией:

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

Добавлен в уровень API 1

Создает ColorStateList, который возвращает указанное отображение из состояний в цвета.

Может кто-нибудь объяснить мне, как это сделать?

В чем смысл двумерного массива для состояний?

Ответ 1

См. 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);

Ответ 2

Первое измерение представляет собой массив состояний, второе - это состояние. Массив цветов отображает цвета для каждого подходящего набора состояний, поэтому длина массива цветов должна соответствовать первому размеру массива состояний (или он будет сбой при использовании состояния). Здесь и пример:

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

надеюсь, что это поможет.

Пример EDIT: список состояний цвета 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)
        }
);

Ответ 3

Иногда этого будет достаточно:

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

Ответ 4

К сожалению, ни одно из решений не работает для меня.

  • Если вы не настроили нажатое состояние сначала, оно не обнаружит его.
  • Если вы установите его, вам нужно определить пустое состояние, чтобы добавить цвет по умолчанию
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

Вот пример того, как создать ColorList программно в Kotlin:

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

Ответ 6

Мой класс конструктора для создания 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);

Ответ 7

если вы используете ресурс 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);

Ответ 8

Отражая ответ Джонатана Эллиса, в Kotlin вы можете определить вспомогательную функцию, чтобы сделать код немного более идиоматичным и проще для чтения, поэтому вы можете написать это вместо этого:

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())
}