最近太忙,所以很久没有写新文章了。这次我们来讨论一下Drawable设置alpha的一个BUG。
一般来说,Drawable做alpha动画都是通过设置alpha来实现。比如使用
drawable.setAlpha(0);
...
drawable.setAlpha(255);
其中0是全透明,255是全不透明。
其实这里有一个很大的BUG,其中牵涉到Drawable的类型。我们以BitmapDrawable和NinePatchDrawable来举例。
在NinePatchDrawable中,设置Alpha值的代码如下:
@Override
public void setAlpha(int alpha) {
if (mPaint == null && alpha == 0xFF) {
// Fast common case -- leave at normal alpha.
return;
}
getPaint().setAlpha(alpha);
invalidateSelf();
}
其中getPaint()的代码如下:
public Paint getPaint() {
if (mPaint == null) {
mPaint = new Paint();
mPaint.setDither(DEFAULT_DITHER);
}
return mPaint;
}
也就是说,NinePatchDrawable设置alpha值的时候,会使用本身所有的一个Paint对象来实现Alpha值的变化。
再回头看看BitmapDrawable的实现。
@Override
public void setAlpha(int alpha) {
int oldAlpha = mBitmapState.mPaint.getAlpha();
if (alpha != oldAlpha) {
mBitmapState.mPaint.setAlpha(alpha);
invalidateSelf();
}
}
请注意,BitmapDrawable中,Paint对象实际是BitmapState的变量,而不是BitmapDrawable本身的。让我们找找BitmapState是从哪儿来的。
一般来说,我们的Drawable都是从resource里面读取而不是自己创建,所以,我们先聚焦从resource读取drawable的情况,所有从resource中读取Drawable的调用最终会调用到loadDrawable()。如下所示:
/*package*/ Drawable loadDrawable(TypedValue value, int id)
throws NotFoundException {
if (TRACE_FOR_PRELOAD) {
// Log only framework resources
if ((id >>> 24) == 0x1) {
final String name = getResourceName(id);
if (name != null) an