Android自定義View(4) 《Canvas基本使用》

概述

在Android中,我們經(jīng)常會(huì)需要去繪制一些自己需要的控件,所以繼承自View的自定義View就產(chǎn)生了。這篇文章主要介紹在View中的重要類,Canvas類的一些基本使用。

Canvas繪制背景

Canvas繪制背景主要有幾個(gè)方法

    /**
     * 使用srcover-porterduff模式,用指定的顏色填充整個(gè)畫布的位圖(限于當(dāng)前剪輯)
     *
     * @param color the color to draw onto the canvas
     */
    public void drawColor(@ColorInt int color) {
        super.drawColor(color);
    }
   /**
     * 使用srcover-porterduff模式,用指定的顏色填充整個(gè)畫布的位圖(限于當(dāng)前剪輯)
     *
     * @param color the {@code ColorLong} to draw onto the canvas. See the {@link Color}
     *              class for details about {@code ColorLong}s.
     * @throws IllegalArgumentException if the color space encoded in the {@code ColorLong}
     *                                  is invalid or unknown.
     */
    public void drawColor(@ColorLong long color){
        super.drawColor(color, BlendMode.SRC_OVER);
    }
   /**
     * 使用指定的顏色和porter duff xfermode填充整個(gè)畫布的位圖(僅限于當(dāng)前剪輯)。
     *
     * @param color the color to draw onto the canvas
     * @param mode the porter-duff mode to apply to the color
     */
    public void drawColor(@ColorInt int color, @NonNull PorterDuff.Mode mode) {
        super.drawColor(color, mode);
    }
   /**
     * 使用指定的顏色和blendmode填充整個(gè)畫布的位圖(僅限于當(dāng)前剪輯)。
     *
     * @param color the color to draw onto the canvas
     * @param mode the blendmode to apply to the color
     */
    public void drawColor(@ColorInt int color, @NonNull BlendMode mode) {
        super.drawColor(color, mode);
    }
  /**
     * 使用指定的顏色和blendmode填充整個(gè)畫布的位圖(僅限于當(dāng)前剪輯)。
     *
     * @param color the {@code ColorLong} to draw onto the canvas. See the {@link Color}
     *              class for details about {@code ColorLong}s.
     * @param mode the blendmode to apply to the color
     * @throws IllegalArgumentException if the color space encoded in the {@code ColorLong}
     *                                  is invalid or unknown.
     */
    public void drawColor(@ColorLong long color, @NonNull BlendMode mode) {
        super.drawColor(color, mode);
    }

畫布的平移

一般采用下面的方法進(jìn)行canvas的平移

   /**
     * Preconcat the current matrix with the specified translation
     *
     * @param dx The distance to translate in X
     * @param dy The distance to translate in Y
    */
    public void translate(float dx, float dy) {
        if (dx == 0.0f && dy == 0.0f) return;
        nTranslate(mNativeCanvasWrapper, dx, dy);
    }

這個(gè)方法可以將canvas的參考坐標(biāo)平移,并不是平移之前已經(jīng)繪制的內(nèi)容,看下面一個(gè)例子大家就明白了,代碼步驟是這樣

  • 繪制一個(gè)矩形
  • 平移畫布
  • 再繪制一個(gè)矩形
    代碼如下
@Override
    protected void onDraw(Canvas canvas){
        super.onDraw(canvas);
        Log.d(TAG,"onDraw");
        // 設(shè)置畫筆的寬度
        paint.setStrokeWidth(5f);
        // 設(shè)置畫筆的顏色
        paint.setColor(Color.RED);
        // 設(shè)置畫筆的Style
        paint.setStyle(Paint.Style.STROKE);
        // 繪制一個(gè)矩形
        canvas.drawRect(rectF,paint);
        // 平移畫布
        canvas.translate(100,100);
        // 繪制矩形
        rectF = new RectF(width/2-300,height/2-150,width/2+300,height/2+150);
        canvas.drawRect(rectF,paint);
    }

運(yùn)行結(jié)果是這樣的


device-2021-08-29-185700.png

明白了吧,canvas只是你繪制時(shí)的一個(gè)圖層而已,當(dāng)你平移之后,并不影響之前已經(jīng)繪制過的內(nèi)容,所以在使用平移畫布時(shí)請記得這點(diǎn)。

Canvas的裁剪,狀態(tài)的保存和恢復(fù)

1.畫布的裁剪

在學(xué)習(xí)裁剪之前,需要先搞清楚一個(gè)概念,這里畫布的裁剪的意義與我們所理解的裁剪紙張的意義是不一樣的,這里的裁剪好比你原本可以在一張完整的紙上進(jìn)行繪制,裁剪后,就好像你的紙張被一張透明的玻璃蓋住,中間你裁剪的部分就是空心的,可以往下面的紙張上繼續(xù)畫東西,其余部分則無法繪制,你只能看到之前繪制的內(nèi)容,你如果裁剪出是一個(gè)圓形,那么你就是在這個(gè)圓中繪制你的內(nèi)容,但是這并不影響顯示你之前已經(jīng)在紙上繪制出來的內(nèi)容.
非常重要的點(diǎn)
裁剪是不可逆的 ! ! !
裁剪是不可逆的 ! ! !
裁剪是不可逆的 ! ! !
所以我們在使用裁剪時(shí)如果需要恢復(fù),是必須要結(jié)合畫布的保存和恢復(fù)一起使用的.裁剪使用的方法主要有以下幾種
還要注意一點(diǎn) 使用裁剪時(shí)需要關(guān)閉硬件加速

setLayerType(LAYER_TYPE_SOFTWARE,null);
  • clipOutRect()系列的函數(shù),主要用來裁剪出一個(gè)矩形之外的部分
  • clipRect()系列的函數(shù),主要用來裁剪出一個(gè)矩形
  • clipOutPath()系列的函數(shù),主要用來裁剪出一個(gè)路徑外的部分,一般是封閉的圖形
  • clipPath()系列的函數(shù),主要用來裁剪出一個(gè)路徑內(nèi)的部分,一般為封閉圖形

2.畫布的狀態(tài)保存與恢復(fù)

  • 保存
    int save()
  • 恢復(fù)
    void restore()
  • 恢復(fù)到指定狀態(tài)
    void restoreToCount(int saveCount)
    這里我們結(jié)合一個(gè)具體的例子來進(jìn)行說明,例子的繪制步驟是這樣的
  • 1.給Canvas一個(gè)綠色背景
  • 2.保存Canvas狀態(tài)
  • 3.在中心裁剪出一個(gè)矩形
  • 4.在裁剪后的Canvas中加入灰色背景色
  • 5.恢復(fù)畫布狀態(tài)
  • 6.在恢復(fù)后的Canvas上畫一個(gè)裁剪范圍之外的藍(lán)色的矩形框
    好了我們開始寫代碼,代碼也很簡單
@Override
    protected void onDraw(Canvas canvas){
        super.onDraw(canvas);
        Log.d(TAG,"onDraw");
        // 設(shè)置畫筆的寬度
        paint.setStrokeWidth(10f);
        // 設(shè)置畫筆的顏色
        paint.setColor(Color.BLUE);
        // 設(shè)置畫筆的Style
        paint.setStyle(Paint.Style.STROKE);

        // 繪制背景色綠色
        canvas.drawColor(Color.GREEN);
        // 保存此時(shí)畫布狀態(tài)
        int saveCount = canvas.save();
        // 在畫布中間裁剪出一個(gè)矩形
        RectF rectF = new RectF(width/2-300,height/2-150,width/2+300,height/2+150);
        canvas.clipRect(rectF);
        // 繪制灰色背景方便觀察
        canvas.drawColor(Color.GRAY);
        // 恢復(fù)畫布狀態(tài),即裁剪之前
        canvas.restoreToCount(saveCount);
        // canvas.restore(); 恢復(fù)至上一個(gè)保存狀態(tài),這里和canvas.restoreToCount(saveCount)效果是一致的,擇一調(diào)用即可。
        // 恢復(fù)后繪制一個(gè)矩形
        RectF rectB = new RectF(20,20,width-20,height-20);
        canvas.drawRect(rectB,paint);
    }

運(yùn)行結(jié)果如下


device-2021-08-29-200319.png

為了驗(yàn)證我們的Canvas恢復(fù)是有效的,我們把恢復(fù)的代碼注釋掉,像這樣

        // 恢復(fù)畫布狀態(tài),即裁剪之前
        // canvas.restoreToCount(saveCount);

運(yùn)行后變成了這樣


device-2021-08-29-200553.png

我們最后繪制的藍(lán)色矩形框沒了,所以裁剪后在裁剪范圍外繪制的內(nèi)容是無效的,但是裁剪前繪制的內(nèi)容是不影響顯示的,所以這樣可以理解裁剪時(shí)類似透明玻璃層的概念了吧

總結(jié)

Canvas的背景繪制,平移,狀態(tài)保存和恢復(fù)就整理到這里了,下篇總結(jié)一下視圖動(dòng)畫~

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

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

  • 項(xiàng)目需求:本項(xiàng)目中為自己的畢設(shè)項(xiàng)目,其中有一個(gè)模塊需要通過APP進(jìn)行碼垛設(shè)計(jì),并將碼垛的結(jié)果發(fā)送給機(jī)械手的控制器。...
    Android_開發(fā)者閱讀 764評論 0 1
  • 上篇文章我們羅列了一個(gè)些Paint的API,本章我們來看一個(gè)下Canvas相關(guān)的API canvas畫布的意思,所...
    TianFB閱讀 320評論 0 1
  • 【Android 自定義View之繪圖】 基礎(chǔ)圖形的繪制 一、Paint與Canvas 繪圖需要兩個(gè)工具,筆和紙。...
    Rtia閱讀 12,164評論 5 34
  • 【Android 自定義View之繪圖】 基礎(chǔ)圖形的繪制 一、Paint與Canvas 繪圖需要兩個(gè)工具,筆和紙。...
    maiduoduo閱讀 3,389評論 0 3
  • 16宿命:用概率思維提高你的勝算 以前的我是風(fēng)險(xiǎn)厭惡者,不喜歡去冒險(xiǎn),但是人生放棄了冒險(xiǎn),也就放棄了無數(shù)的可能。 ...
    yichen大刀閱讀 7,922評論 0 4

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