天天看點

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的時候,要多多關注一下新功能,新改進,這樣在開發過程中也能降低這種風險。