Android Canvas

Android官方源碼中對(duì)Canvas的描述是:“Canvas類容納所有和Draw(繪制)相關(guān)方法。為了去Draw些東西,你需要具備4個(gè)基礎(chǔ)要素:1個(gè)Bitmap用來承載像素信息,1個(gè)Canvas用來管理Draw相關(guān)方法(寫入Bitmap中),1個(gè)繪圖基元(例如,Rect,Path,text,Bitmap),1個(gè)畫筆(用于描繪圖像的顏色和風(fēng)格)。

這和我們?nèi)粘@斫獾睦L畫異曲同工,Bitmap作為畫布,Canvas管理著繪畫的手法,繪圖基元代表著要繪制的目標(biāo),Paint就是你手里的畫筆和顏料。

如何得到1個(gè)Canvas對(duì)象

  1. 之前提到的onDraw方法的入口參數(shù)就是Canvas,我們用變量承載它,就可以使用,而我們操作這個(gè)Canvas最終的效果會(huì)直接反應(yīng)在這個(gè)View上。
  2. SurfaceView是View的繼承了,其內(nèi)部有專門的線程來完成畫圖的工作,而不用像View一樣需要等待刷新,主要用在游戲和高品質(zhì)動(dòng)畫方面。既然是View的繼承類,SurfaceView自然可以獲取到Canvas的對(duì)象,方式是通過調(diào)用SurfaceView的好基友SurfaceHolder的lockCanvas()方法。
  3. 當(dāng)然,除了獲取View或SurfaceView自帶的現(xiàn)成的Canvas對(duì)象,我們還可以自己創(chuàng)建。從4大基本要素我們就可以知道,1個(gè)Canvas對(duì)象一定要結(jié)合1個(gè)Bitmap對(duì)象。所以一定要為新建的Canvas對(duì)象設(shè)置1個(gè)Bitmap對(duì)象。
/**
 * 得到一個(gè)Bitmap對(duì)象,當(dāng)然也可以使用別的方式得到。但是要注意,改bitmap一定要是mutable(異變的)
 * mutable : 易變的,不定的
 * mutable 作用 :  控制bitmap的setPixel方法能否使用,也就是外界能否修改bitmap的像素。
 * Bitmap.createBitmap(mWidth, mHeight, Config.ARGB_8888) 為 mutable 為true
 * BimapFactory.decodeResource() 得到的mutable 為false, 要想其為true
 * 一般會(huì)BimtapFactory.decodeResource().copy(configu_argb_8888, true);
 * 先new一個(gè)Canvas對(duì)象,在調(diào)用setBitmap方法,一樣的效果
 * Canvas c = new Canvas();
 * c.setBitmap(b);
 */
Bitmap b = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
Canvas canvas2 = new Canvas(b);

Canvas能畫些什么

Canvas類提供了若干draw……的方法,從字面上我們就可以知道用這些方法我們可以繪制哪些東西。

填充

Canvas內(nèi)部維持了一個(gè)mutable Bitmap,所以我們可以用顏色來填充整個(gè)Bitmap。而填充的范圍受限于clip的范圍。

  • drawRGB(int r, int g, int b):r-紅色要素(0255),g-綠色要素(0255),b-藍(lán)色要素(0~255)。
  • drawARGB(int a, int r, int g, int b):a-透明度(0255),r-紅色要素(0255),g-綠色要素(0255),b-藍(lán)色要素(0255)。
  • drawColor(int color):這里的color要為16進(jìn)制的顏色號(hào),例如:0xFF000000,共8位,兩位一組從左到右分別為ARGB,具體含義同上。若要使用“#FF000000”這樣的色號(hào),可以調(diào)用Color.parseColor(String colorString)方法來進(jìn)行轉(zhuǎn)換。
  • drawColor(int color, PorterDuff.Mode mode):color同上,PorterDuff.Mode比較有意思,有很多種模式,每一種模式都會(huì)有特定的效果,感興趣的朋友可以自行了解一下。
  • drawPaint(Paint paint):Canvas同樣可以用畫筆來填充Bitmap,當(dāng)然也受限于clip的范圍。

繪制圖形

  • canvas.drawArc (扇形)
  • canvas.drawCircle(圓)
  • canvas.drawOval(橢圓)
  • canvas.drawLine(線)
  • canvas.drawPoint(點(diǎn))
  • canvas.drawRect(矩形)
  • canvas.drawRoundRect(圓角矩形)
  • canvas.drawVertices(頂點(diǎn))
  • cnavas.drawPath(路徑)

繪制圖片

  • canvas.drawBitmap(位圖)
  • canvas.drawPicture(圖片)

文本

  • canvas.drawText

Canvas的變換

Canvas不僅僅可以draw一些圖形、圖片,其本身也提供了可操作的方法:rorate(旋轉(zhuǎn))、scale(壓縮)、translate(平移)、skew(扭曲)等。

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    canvas.drawRect(new Rect(0, 0, 200, 200), new Paint());
    canvas.scale(0.5f, 0.5f);//縮放了
    canvas.drawRect(new Rect(400, 400, 600, 600), new Paint());

    canvas.translate(600, 600);//平移了
    canvas.rotate(45);//旋轉(zhuǎn)了
    canvas.drawRect(new Rect(0, 0, 200, 200), new Paint());

    canvas.translate(200, 200);
    canvas.skew(.5f, .5f);//扭曲了
    canvas.drawRect(new Rect(0, 0, 200, 200), new Paint());
}
blog-20160309-1.png

Canvas的保存和回滾

為了配合Canvas本身的變換操作,Canvas提供了保持當(dāng)前狀態(tài)和回滾的方法。來個(gè)小例子。
我們準(zhǔn)備畫一個(gè)表盤,那么我們就有兩種實(shí)現(xiàn)的思路:

  1. 表盤上有60個(gè)刻度,每個(gè)刻度之間間隔6°,這是有規(guī)律的,那么我們就可以利用三角函數(shù)的知識(shí)來把刻度的兩個(gè)坐標(biāo)求出來,再利用drawLine畫到Canvas上??简?yàn)?zāi)氵壿嬎季S和數(shù)學(xué)功底的時(shí)候到了,不用仔細(xì)想就能知道這個(gè)方法有點(diǎn)麻煩。
  2. 如果不喜歡第一種方法,那么我們可以嘗試一下這一種。Canvas提供了旋轉(zhuǎn)操作的方法,也提供了保存和回復(fù)狀態(tài)的方法,那么我們就用這些搭配起來。首先我在(100,0)和(100,10)兩個(gè)坐標(biāo)之間畫一條豎線,很簡單,整點(diǎn)的刻度就出來了。之后先將Canvas的狀態(tài)保存起來,在(100,0)和(100,10)兩個(gè)坐標(biāo)之間畫一條豎線,回復(fù)Canvas的狀態(tài),一分鐘的刻度就出來了。以此類推,思路是不是很簡單。
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    for (int i = 0; i < 360; i = i + 6) {
        canvas.save();
        canvas.rotate(i, 100, 100);
        canvas.drawLine(100, 0, 100, 10, new Paint());
        canvas.restore();
    }
}
blog-20160309-2.png
最后編輯于
?著作權(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)容

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