继承关系
- ColorStateList
.
|--Object
├─ColorStateList
- StateListDrawable
.
|--Object
| ├─Drawable
| ├─ColorDrawable
| ├─**StateListDrawable**
用法
ColorStateList
多状态颜色的ColorStateList
java:
// 颜色数组 int[] colors = new int[]{color, color1, color2, color3, color4, color5}; // 颜色数组对应的状态 int[][] states = new int[6][]; states[0] = new int[]{android.R.attr.state_checked, android.R.attr.state_enabled}; states[1] = new int[]{android.R.attr.state_enabled, android.R.attr.state_focused}; states[2] = new int[]{android.R.attr.state_enabled}; states[3] = new int[]{android.R.attr.state_focused}; states[4] = new int[]{android.R.attr.state_window_focused}; states[5] = new int[]{}; ColorStateList colorList = new ColorStateList(states, colors)
xml:
<!--test.xml--> <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="@color/colorTextWhite" android:state_enabled="false"/> <item android:color="@color/colorAccent" /> </selector>
单种颜色ColorStateList
java:
int color = 0xff00ff00 ColorStateList colorList = ColorStateList.valueOf(color);
xml:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="@color/colorAccent" /> </selector>
注意
如果一个xml的方式创建,xml文件要位于res/color/目录,而不是 res/drawable/ 目录。
StateListDrawable
xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@color/colorPrimaryDark" android:state_checked="true" /> <item android:drawable="@color/colorAccent" /> </selector>
java
StateListDrawable sld = new StateListDrawable(); sld.addState(new int[]{android.R.attr.state_checkable},new ColorDrawable(0xfff)); v.setBackground(sld);
注意
addState先添加,优先匹配
共同点
两者具有状态属性 ,状态定义在
android.R.attr
中:android:state_pressed=["true" | "false"] android:state_focused=["true" | "false"] android:state_selected=["true" | "false"] android:state_checkable=["true" | "false"] android:state_checked=["true" | "false"] android:state_enabled=["true" | "false"] android:state_window_focused=["true" | "false"]
选择方式
都是至上而下匹配(xml从上到下,java中int[] 从0~n),如果单个item中有两张状态声明,则同时满足两个状态才匹配成功
默认值
当所有条件都不满足的时候,会返回默认值。也就是最后一个值。
不同点
xml文件位置
ColorStateList 对应的xml文件位于res/color中
StateListDrawable 对应的xml文件位于res/drawable中
用途
ColorStateList 用于颜色选择
StateListDrawable 用于Drawable选择
思考
color,ColorStateList 与 ColorDrawable
color
是一种颜色,ColorStateList
是根据状态的多种颜色,ColorDrawable
是一个可绘制对象。color
可以转化为ColorStateList
,color
也可以转化为ColorDrawable
;ColorStateList
与ColorDrawable
没关系。假如我们要设置背景颜色:
public class View{ private Drawable mBackground; public void setBackgroundColor(@ColorInt int color) { if (mBackground instanceof ColorDrawable) { ((ColorDrawable) mBackground.mutate()).setColor(color); computeOpaqueFlags(); mBackgroundResource = 0; } else { setBackground(new ColorDrawable(color)); } } }
color首先会被转换为ColorDrawable , 因为绘制背景时不会有一个Paint去绘制这个颜色。而是Drawable直接绘制在Canves上。
为什么 同样是
<select></select>
标签,内容是color和内容是drawble要分别放在res/color/ 和 res/drawable/文件夹?res/drawable/test_color.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="@color/colorTextWhite" android:state_enabled="false" /> <item android:color="@color/colorAccent" android:state_enabled="true" /> </selector>
res/drawable/test_drawable.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/img_a" android:state_checked="true" /> <item android:drawable="@drawable/img_b" android:state_checked="false"/> </selector>
首先他们对应的java类不同,test_drawable.xml 使用时会反射生成
StateListDrawable
,而test_color.xml 使用时会反射生成ColorStateList
.而ColorStateList
并不时drawable的子类,也就是说它不是一个drawable。也就没理由放到drawable目录下。为什么 res/value/colors/xml 下的颜色资源 和res/color/xx.xml下的资源可以都使用 @color/xx 使用?
res/value/colors/xml
下的color是一个单一颜色值res/color/**.xml
下是和状态有关的多个颜色值.他们的关系类似 单个image是一个drawble 而 StateListDrawable 是 和状态有关的多个drawable,都是drawable所以就@drawable。
类似,都是用来表示颜色,所以就都@color
为什么同样是设置颜色,
setBackground
使用res/drawable/
, 而setTextColor
使用res/color/
?setBackground
需求的参数是Drawable
,如果是颜色,颜色会被转换成ColorDrawable
。如果需要多个颜色,使用res/drawable/
下的selector
,转化为StateListDrawable,每个state都是一个ColorDrawable。也就是说,这里面的color一定转为ColorDrawable使用。setTextColor
需求的参数是color
,res/color/colors.xml
和res/color/**.xml
都会转化为ColorStateList
。ColorStateList
用来提供color。