【问题标题】:How do I create ColorStateList programmatically?如何以编程方式创建 ColorStateList?
【发布时间】:2013-03-10 16:57:36
【问题描述】:

我正在尝试使用以下代码以编程方式创建ColorStateList

ColorStateList stateList = new ColorStateList(states, colors); 

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

根据文档:

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

在 API 级别 1 中添加

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

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

状态的二维数组是什么意思?

【问题讨论】:

    标签: android android-color


    【解决方案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);
    

    【讨论】:

    • 感谢有关“相反”状态的信息!
    • 这可用于从设计库中更改工厂的颜色。
    • 注意:请参阅 Roger Alien 的回答(及其第一条评论)以了解此处的状态顺序很差:因为“启用”是第一个,所以它将覆盖通常在按钮打开时发生的其他状态启用。最好把“启用”放在最后。 (或者不是“启用”,而是最后一个空/默认项目。)
    • 不保留状态(不是切换/复选框)的按钮的基本状态列表可能是{pressed}{focused}{-enabled}{}。对于切换,它可能是{checked, pressed}{pressed}{checked, focused}{focused}{checked}{-enabled}{}。或者忽略焦点的切换:{checked, pressed}{pressed}{checked}{-enabled}{}
    • 如果有人会尝试这些解决方案,请注意 selector.xml 中的状态顺序!
    【解决方案2】:

    有时这就足够了:

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

    【讨论】:

      【解决方案3】:

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

      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 "schemas.android.com/apk/res/android" > " 使用 colorstatelist。
      • @SatishKumar 检查我的编辑,不过我还没有测试过。
      • 值得一提的是,要指定一个假状态,你可以取反它的值,所以如果你想为它不被按下时指定一个颜色,你应该使用:new int[]{-android. R.attr.state_pressed}
      • 补充@tinsukE 所说的内容:但是,为了避免意外取消列表后面的项目,对于大多数州来说,否定是没有意义的 - 而是处理所有“其他”默认(空)项目new int[]{} last 的可能性 - 如本答案的最终代码块所示。我通常使用的唯一否定值是“启用”。再比如,如果你想要三种不同的颜色:“聚焦+按下”、“聚焦+未按下”、“按下+未聚焦”,你可以简单地输入{focused, pressed}{focused}{pressed}。将使用第一个“真实”的。
      • ... 你可能犯的错误是有一个像{pressed}{-pressed}{focused}{-focused} 这样的系列。问题是{pressed}{-pressed} 涵盖了所有可能性(按钮被按下或未按下),所以后面列出的任何颜色都不会被使用。!
      【解决方案4】:

      这是一个如何在 Kotlin 中以编程方式创建 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
              )
      )
      

      【讨论】:

      【解决方案5】:

      不幸的是,没有一个解决方案适合我。

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

      【讨论】:

      • 旁注:您必须像对待 if-elseif 一样对待它。它选择第一个为真的状态。因此,如果您将 state_enabled 作为第一个状态,它将在 state_pressed 之前被选中 -- 除非视图被禁用。
      • FWIW,因为你最后有一个默认元素,我不认为第一个“启用”元素对你有任何好处。为什么不完全删除它?
      【解决方案6】:

      answer by 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)
      }
      

      这样我就可以调用相同的函数名,无论是选择器还是单色。

      【讨论】:

        【解决方案7】:

        我的构建器类用于创建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);
        

        【讨论】:

          【解决方案8】:

          如果你使用 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);
          

          【讨论】:

          • 因为getResources() 已被弃用,它现在是ContextCompat.getColor(this,R.color.colorname);ContextCompat.getColor(getActivity(),R.color.colorname); 用于片段
          • 为了澄清其他读者,new int[0](作为第一个参数列表中的元素)是一个长度为零的数组,表示设置默认颜色。这里它是唯一的元素,这意味着色调应用于按钮的 所有 状态。这相当于在 Roger Alien 的回答中看到的 new int[]{}
          猜你喜欢
          • 1970-01-01
          • 2013-11-15
          • 2013-12-28
          • 2011-02-10
          • 2011-04-02
          • 2012-02-26
          • 2011-03-01
          • 2014-06-18
          • 1970-01-01
          相关资源
          最近更新 更多