天天看点

Android ColorDrawable那些事

今天在开发过程中遇到一个很蛋痛的问题,最终发现是系统的问,值得总结一下。

前提

我在实现一个基于Adapter的LinearLayout的时候,想在第一个View中间绘制一个间隔线(Divider),接收一个Drawable对象,这是前提。

在绘制间隔线的时候,我的代码是这样的:

private void drawVerticalDividers(Canvas canvas) {
        int count = mShowLastDivider ? getChildCount() : (getChildCount() - 1);
        
        if (null != mDivider && count > 0) {
            int height = mDividerSize;
            int top = 0;
            int offset = (mSpace - height) / 2;
            View child = null;
            Rect bounds = mTempRect;
            bounds.left = getPaddingLeft();
            bounds.right = bounds.left + getWidth() - getPaddingRight();
            
            for (int i = 0; i < count; ++i) {
                child = getChildAt(i);
                top = child.getBottom() + offset;
                bounds.top  = top;
                bounds.bottom = top + height;
                drawDivider(canvas, bounds);
            }
        }
    }
           

在每一个Child的下面绘制一个分隔线,这种算法是没有问题的。

在使用的时候,我设置一个ColorDrawable对象,运行在4.x的系统上面,完全没有问题,但是在2.x的系统上面,结束整个LinearLayout的背景色都变成了我设置的Divider的颜色,这很奇怪呀。我一直在怀疑是不是我的算法有问题,但最终一一排除,发现绘制Drawable的问题,最后就把源码拿出来看,果然,2.x版本的ColorDrawable与4.x的draw()方法实现不一样:

2.x版本的ColorDrawable#draw()实现:

@Override
    public void draw(Canvas canvas) {
        canvas.drawColor(mState.mUseColor);
    }
           

它就简单粗暴地在整个Canvas上面绘制一个color,所以会导致整个View都成了指定的颜色

4.x版本的ColorDrawable#draw()实现

@Override
    public void draw(Canvas canvas) {
        if ((mState.mUseColor >>> 24) != 0) {
            mPaint.setColor(mState.mUseColor);
            canvas.drawRect(getBounds(), mPaint);
        }
    }
           

它是绘制一个bounds的Rect,所以它的绘制区域是我指定的bound。

我是怎么解决这个问题呢?

很简单,在绘制divider之前,用指定的bound来剪切Canvas:

final Drawable divider = mDivider;
        if (null != divider) {
            canvas.save();
            canvas.clipRect(bounds);
            divider.setBounds(bounds);
            divider.draw(canvas);
            canvas.restore();
        }
           

这样就没有问题了。

总结:

只能说Android也在一步一步的完善,它的源码也在不断的进步,这是很好的,这也同时告诉我们,在开发Android应用程序的时候,要多注意到不同OS版本之间的差异性,每当Google推出新版本的OS的时候,要多多关注一下新功能,新改进,这样在开发过程中也能降低这种风险。