如何以编程方式创建ColorStateList?


158

我正在尝试ColorStateList使用此程序创建一个程序:

ColorStateList stateList = new ColorStateList(states, colors); 

但是我不确定这两个参数是什么。

根据文档:

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

在API级别1中添加

创建一个ColorStateList,它返回从状态到颜色的指定映射。

有人可以解释一下如何创建吗?

二维状态数组的含义是什么?

Answers:


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
感谢您提供有关“相反”状态的信息!
BVB 2014年

可以用来从设计库中更改晶圆厂的颜色。
Tapirboy

5
注意:请参阅Roger Alien的答案(及其第一条评论),以了解此处的状态顺序很差:因为首先是“启用”,所以它将覆盖在启用按钮时通常发生的其他状态。最好把“启用”放在最后。(或者代替“已启用”,最后一个空/默认项。)
ToolmakerSteve

2
国家对一个按钮,不保留状态(而不是切换/复选框)可能是一个基本的清单{pressed}{focused}{-enabled}{}。对于拨动它可能是{checked, pressed}{pressed}{checked, focused}{focused}{checked}{-enabled}{}。或者拨动忽略重点:{checked, pressed}{pressed}{checked}{-enabled}{}
ToolmakerSteve

如果有人尝试这些解决方案中的任何一种,请注意选择器.xml中的状态顺序!
安东·马可夫

75

第一维是状态集的数组,第二维是状态集本身。colors数组列出了每个匹配状态集的颜色,因此colors数组的长度必须匹配状态数组的第一个维度(否则在“使用”状态时它将崩溃)。这里和例子:

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_pressed =” true“ android:color =” @ color / white“ / > <item android:color =“ @ color / black” /> </ selector>使用colorstatelist。
Satish

@SatishKumar检查我的编辑,虽然我没有测试过。
Su-Au Hwang 2014年

3
值得一提的是,要指定一个错误状态,您可以取反它的值,因此,如果要为未按下状态指定一种颜色,则应使用:new int [] {
-android.R.attr.state_pressed

1
要补充@tinsukE所说的内容:但是,为了避免在列表的后面意外删除某个项目,对于大多数州来说,否定是没有意义的-而是使用默认(空)项目处理所有“其他”可能性new int[]{}最后-如此答案的最终代码块所示。我通常使用的唯一取反值是“启用”。另外一个例子,如果你想三种不同的颜色:“集中+按下”,“集中+未按”,“按下+不集中”,你可以简单地说{focused, pressed}{focused}{pressed}。将使用第一个“ true”。
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
就像一个旁注:您必须像对待if-elseif一样对待它。它选择第一个为真的状态。因此,如果将state_enabled作为第一个状态,则将在state_pressed之前选择它-除非禁用了视图。
LeoFarage '16

FWIW,因为您最后有一个默认元素,所以我认为第一个“启用”元素根本对您没有任何好处。为什么不将其完全删除?
ToolmakerSteve

18

这是一个如何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
        )
)

另外,请参阅下面有关Kotlin助手功能的答案
arekolek

7

乔纳森·埃利斯(Jonathan Ellis)答案出发,在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())
}

我也有:

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[]{}于Roger Alien的回答。
ToolmakerSteve
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.