Android自定義控件二(View的測量和繪制)

現(xiàn)實生活中,如果我們要去畫一個圖形,就必須知道它的位置和大小。
Android系統(tǒng)在繪制View前,也必須對View進行測量,這個過程在onMeasure()方法中進行。

MeaSureSpec
Android 提供的測量View的一個類,是一個32位int值,其中高2位為測量模式,低30位為測量大小(size)。

測量模式可分為3類:
  • EXACTLY
    精確值模式:將layout_width或layout_height屬性指定為具體數(shù)值(30dp)或者match_parent
  • AT_MOST
    最大值模式:將layout_width或layout_height指定為wrap_content。
  • UNSPECIFIED
    View想多大就多大。通常在自定義View才會使用。
注意:

View的默認哦那Measure()只支持EXACTLY,
如果讓自定的view支持wrap_content,必須重寫onMeasure()來指定wrap_content大小。

簡單示例:
public class MeasuredView extends View {
    public MeasuredView(Context context) {
        super(context);
    }
    
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // 調(diào)用父類的onMeasure()
        super.onMeasure(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
        // 或者直接調(diào)用父類的setMeasuredDimension(),因為父類的onMeasure()最終調(diào)用了setMeasuredDimension()
        // setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
    }
    
    /**
     * 測量View的width
     * @param measureSpec MeasureSpec對象
     * @return View的width
     */
    private int measureWidth(int measureSpec) {
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        
        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        } else {
            result = 200;
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }
        return result;
    }
    
    /**
     * 測量View的height
     * @param measureSpec MeasureSpec對象
     * @return View的height
     */
    private int measureHeight(int measureSpec) {
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        
        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        } else {
            result = 200;
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }
        return result;
    }
}

View的繪制

2D繪圖必備利器——Canvas
獲取Canvas對象的方式:
a. 由方法中的參數(shù)傳入,例如,View的onDraw()中有一個參數(shù)就是Canvas對象
b. 通過構(gòu)造方法構(gòu)造,即:Canvas canvas = new Canvas(bitmap),在Canvas的構(gòu)造方法傳入一個Bitmap對象,即可獲取一個Canvas對象。通過傳入Bitmap對象構(gòu)造Canvas對象的過程稱為“畫布的裝載”,傳入的Bitmap對象承載了多有繪制在Canvas上的像素信息,調(diào)用Canvas.drawXXX方法(如:Canvas.drawBitmap(bitmap, 0, 0, null))都將發(fā)生在該Bitmap對象上。

利用Canvas繪圖
a. 通過Canvas.drwaXXX進行繪制操作將直接作用于Bitmap對象,當再次刷新View的時候,我們將會被繪制的Bitmap對象發(fā)生了改變;
b. 利用Canvas和Paint進行繪圖;
c. 不管多么復雜、精美的空間,都可以被拆分為一個個小的圖形單元,我們只要找到這些圖形單元,就可以將控件繪制出來。

參考:Android群英傳
Android視圖控件架構(gòu)分析之View、ViewGroup

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容