前几天在做项目的时候发现一个问题,就是new了一个ColorDrawable,设置了色值,但是一直看不到效果。先把代码贴一下吧
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ImageView im = (ImageView) findViewById(R.id.im);
ColorDrawable d = new ColorDrawable(0xff0000);
im.setBackgroundDrawable(d);
}
}
代码很简单,就是为一个ImageView设置了一个ColorDrawable,色值为0xff0000,也就是红色。但是实际效果却是看不到红色,给人的感觉就是这个imageview什么也没显示。于是就去看了下ColorDrawable的源码,希望可以找到原因。这里用的是api18的android源码。
public ColorDrawable(int color) {
this(null);
setColor(color);
}
public void setColor(int color) {
if (mState.mBaseColor != color || mState.mUseColor != color) {
invalidateSelf();
mState.mBaseColor = mState.mUseColor = color;
}
}
在ColorDrawable的源码中有上面两个方法,这两个方法也很简单就是为ColorDrawable设置一个色值。然后将色值保存在本地的Constant变量中。这里似乎看不出什么问题,接下来再看下ColorDrawable的draw方法。
public void draw(Canvas canvas) {
if ((mState.mUseColor >>> 24) != 0) {
mPaint.setColor(mState.mUseColor);
canvas.drawRect(getBounds(), mPaint);
}
}
这个方法也比较简单,就是在canvas上画一个给定色值的矩形。但是在绘制之前有个判断,就是(mState.mUseColor >>> 24) != 0。也就是会对色值进行右移24位,然后看值是不是为0(这里其实就是看alpha值),如果为0就不画了,不为0才画。
看下我们之前设置的色值是0xff0000,右移24位之后为0,所以就不画了,也就不显示颜色了。所以解决方法就是在色值上加上alpha值。比如new ColorDrawable(0xffff0000)。就可以正常显示了。
上面的问题分析完之后,还有一个疑问,就是在xml中定义的色值又是可以生效的。比如在xml中定义了一个imageview,设置背景色值为ff0000
<ImageView
android:id="@+id/im"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#ff0000"
/>
这样在Activity中又可以正常显示这个色值(这里是红色)。这又是为什么呢?我的理解是activiity在解析这个xml时会去解析这个色值。而这个色值的解析是通过Color类去解析的。看下Color类的解析色值的函数
public static int parseColor(String colorString) {
if (colorString.charAt(0) == '#') {
// Use a long to avoid rollovers on #ffXXXXXX
long color = Long.parseLong(colorString.substring(1), 16);
if (colorString.length() == 7) {
// Set the alpha value
color |= 0x00000000ff000000;
} else if (colorString.length() != 9) {
throw new IllegalArgumentException("Unknown color");
}
return (int)color;
} else {
Integer color = sColorNameMap.get(colorString.toLowerCase(Locale.US));
if (color != null) {
return color;
}
}
throw new IllegalArgumentException("Unknown color");
}
这里在解析色值的时候回去检查给的色值是几位的,如果String在#后是6位(也就是这个色值是不带alpha值的),会将这个色值加上alpha为ff,也就是不透明(通过color |= 0x00000000ff000000 这个实现的)。这样再通过这个色值new ColorDrawable的时候就可以正常显示了。