Android Canvas繪圖詳解

Android中使用圖形處理引擎,2D部分是android SDK內(nèi)部自己提供,3D部分是用Open GL ES 1.0

大部分2D使用的api都在android.graphics和android.graphics.drawable包中。他們提供了圖形處理相關(guān) 的: Canvas、ColorFilter、Point(點)和RetcF(矩形)等,還有一些動畫相關(guān)的:AnimationDrawable、 BitmapDrawable和TransitionDrawable等。以圖形處理來說,我們最常用到的就是在一個View上畫一些圖片、形狀或者自定 義的文本內(nèi)容,這里我們都是使用Canvas來實現(xiàn)的。你可以獲取View中的Canvas對象,繪制一些自定義形狀,然后調(diào)用View. invalidate方法讓View重新刷新,然后繪制一個新的形狀,這樣達到2D動畫效果。下面我們就主要來了解下Canvas的使用方法。

Canvas對象的獲取方式有兩種:一種我們通過重寫View.onDraw方法,View中的Canvas對象會被當做參數(shù)傳遞過來,我們操作這個Canvas,效果會直接反應(yīng)在View中。另一種就是當你想創(chuàng)建一個Canvas對象時使用的方法:

1

2Bitmap b = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);

Canvas c =newCanvas(b);

上 面代碼創(chuàng)建了一個尺寸是100*100的Bitmap,使用它作為Canvas操作的對象,這時候的Canvas就是使用創(chuàng)建的方式。當你使用創(chuàng)建的 Canvas在bitmap上執(zhí)行繪制方法后,你還可以將繪制的結(jié)果提交給另外一個Canvas,這樣就可以達到兩個Canvas協(xié)作完成的效果,簡化邏 輯。但是android SDK建議使用View.onDraw參數(shù)里提供的Canvas就好,沒必要自己創(chuàng)建一個新的Canvas對象。接下來我們看看Canvas提供我們哪些 繪制圖形的方法。我們創(chuàng)建一個自定義View對象,使用onDraw方法提供的Canvas進行繪制圖形。

CanvasDemoActivity.java:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47package com.android777.demo.uicontroller.graphics;

import android.app.Activity;

import android.content.Context;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.os.Bundle;

import android.view.View;

public class CanvasDemoActivity extends Activity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(newCustomView1(this));

}

/**

* 使用內(nèi)部類 自定義一個簡單的View

* @author Administrator

*

*/

class CustomView1 extends View{

Paint paint;

public CustomView1(Context context) {

super(context);

paint =newPaint();//設(shè)置一個筆刷大小是3的黃色的畫筆

paint.setColor(Color.YELLOW);

paint.setStrokeJoin(Paint.Join.ROUND);

paint.setStrokeCap(Paint.Cap.ROUND);

paint.setStrokeWidth(3);

}

//在這里我們將測試canvas提供的繪制圖形方法

@Override

protected void onDraw(Canvas canvas) {

}

}

}

執(zhí)行結(jié)果是一片黑色的區(qū)域,因為在自定義的CustomView1中,我們沒有做任何的繪制操作。canvas提供的繪制圖形的方法都是以draw開頭的,我們可以查看api:

從上面方法的名字看來我們可以知道Canvas可以繪制的對象有:

弧 線(arcs);

// 繪制弧線區(qū)域

RectF rectF = new RectF(0, 0, 100, 100);

// RectF設(shè)置四個參數(shù)(分別是距離左多少,距離上多少,距離右多少 , 距離下多少);

canvas.drawArc(rectF, 0, 90, false, paint);

------------------------------------------------------------------------------------------------------------------------------

填充顏色(argb和color);

Bitmap;

圓(circle和oval);

// drawCircle (圓的中心被吸引的x坐標 , 坐標中心的圓來繪制 , 半徑的圓來繪制(旋轉(zhuǎn)多少度) , paint對象 );

canvas.drawCircle(100, 100, 90, paint);

-------------------------------------------------------------------------------------------------------------------------------

點(point);

// drawPoint(該點X位置 , 該點的Y位置 ?, paint對象);

canvas.drawPoint(500, 500, paint);

-------------------------------------------------------------------------------------------------------------------------------

線(line);

// drawLine (該線路的起始點的x坐標 , 該線路的起始點的Y坐標 , 線的終點距離屏幕的x坐標的距離 , 該線的長度 , paint對象);

canvas.drawLine(0, 0, 100, 1000, paint);

-------------------------------------------------------------------------------------------------------------------------------

矩形(Rect);

//RectF (該圓距離X的距離,該園距離Y的距離,該圓的寬 ,該圓的上);

RectF rectF = new RectF(10, 10, 100, 100);

canvas.drawOval(rectF, paint);

-------------------------------------------------------------------------------------------------------------------------------

圖片(Picture);

圓角矩形 (RoundRect);

RectF rectF = new RectF(50, 50, 100, 100);

canvas.drawRoundRect(rectF,

30, //x軸的半徑

30, //y軸的半徑

paint);

文本(text);

// drawPosText (要顯示的文本, 文本每一個字母的位置(通過float類型的集合) , paint對象);

canvas.drawPosText("Android", new float[]{10,10,20,20,30,30,40,40,50,50,60,60,70,70}, paint);

-------------------------------------------------------------------------------------------------------------------------------

頂點(Vertices);

路徑(path);

Path path = new Path(); // 定義一條路徑

/*

* 設(shè)置下一個輪廓線的起點(×,)。

*

* @param x x坐標的開始一個新的輪廓

*

* @param Y坐標,開始一種新的輪廓

*/

path.moveTo(10, 10); // 移動到 坐標10,10

/*

* 從最后一個點到指定點(x)加一條線。如果沒有moveto()調(diào)用了這個輪廓,第一點是自動設(shè)置為(0,0)

*/

path.lineTo(60, 60);

path.lineTo(200, 80);

path.lineTo(10, 10);

canvas.drawPath(path, paint);

-------------------------------------------------------------------------------------------------------------------------------

通過組合這些對象我們可以畫出一些簡單有趣 的界面出來,但是光有這些功能還是不夠的,如果我要畫一個儀表盤(數(shù)字圍繞顯示在一個圓圈中)呢? 幸好Android還提供了一些對Canvas位置轉(zhuǎn)換的方法:rorate、scale、translate、skew(扭曲)等,而且它允許你通過獲 得它的轉(zhuǎn)換矩陣對象(getMatrix方法,不知道什么是轉(zhuǎn)換矩陣?看這里) 直接操作它。這些操作就像是雖然你的筆還是原來的地方畫,但是畫紙旋轉(zhuǎn)或者移動了,所以你畫的東西的方位就產(chǎn)生變化。為了方便一些轉(zhuǎn)換操作,Canvas 還提供了保存和回滾屬性的方法(save和restore),比如你可以先保存目前畫紙的位置(save),然后旋轉(zhuǎn)90度,向下移動100像素后畫一些 圖形,畫完后調(diào)用restore方法返回到剛才保存的位置。下面我們就演示下canvas的一些簡單用法:

1

2

3

4protected void onDraw(Canvas canvas) {

canvas.drawCircle(100, 100, 90, paint);

}

效果是:

1

2

3

4

5

6

7

8

9

10

11

12

13

14@Override

protected void onDraw(Canvas canvas) {

//繪制弧線區(qū)域

RectF rect =newRectF(0, 0, 100, 100);

canvas.drawArc(rect,//弧線所使用的矩形區(qū)域大小

0,//開始角度

90,//掃過的角度

false,//是否使用中心

paint);

}

使用下面的代碼:

1

2

3

4

5

6

7

8

9

10

11

12

13protected void onDraw(Canvas canvas) {

//繪制弧線區(qū)域

RectF rect =newRectF(0, 0, 100, 100);

canvas.drawArc(rect,//弧線所使用的矩形區(qū)域大小

0,//開始角度

90,//掃過的角度

true,//是否使用中心

paint);

}

兩 圖對比我們可以發(fā)現(xiàn),當 drawArcs(rect,startAngel,sweepAngel,useCenter,paint)中的useCenter為false時,弧 線區(qū)域是用弧線開始角度和結(jié)束角度直接連接起來的,當useCenter為true時,是弧線開始角度和結(jié)束角度都與中心點連接,形成一個扇形。

1

2

3

4

5protected void onDraw(Canvas canvas) {

canvas.drawColor(Color.BLUE);

}

canvas.drawColor是直接將View顯示區(qū)域用某個顏色填充滿。

1

2

3

4

5

6

7@Override

protected void onDraw(Canvas canvas) {

//畫一條線

canvas.drawLine(10, 10, 100, 100, paint);

}

Canvas.drawOval:

1

2

3

4

5

6

7

8

9@Override

protected void onDraw(Canvas canvas) {

//定義一個矩形區(qū)域

RectF oval =newRectF(0,0,200,300);

//矩形區(qū)域內(nèi)切橢圓

canvas.drawOval(oval, paint);

}

canvas.drawPosText:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18@Override

protected void onDraw(Canvas canvas) {

//按照既定點 繪制文本內(nèi)容

canvas.drawPosText("Android777",newfloat[]{

10,10,//第一個字母在坐標10,10

20,20,//第二個字母在坐標20,20

30,30,//....

40,40,

50,50,

60,60,

70,70,

80,80,

90,90,

100,100

}, paint);

}

canvas.drawRect:

1

2

3

4

5

6

7

8

9

10@Override

protected void onDraw(Canvas canvas) {

RectF rect =newRectF(50, 50, 200, 200);

canvas.drawRect(rect, paint);

}

}

canvas.drawRoundRect:

1

2

3

4

5

6

7

8

9

10

11@Override

protected void onDraw(Canvas canvas) {

RectF rect =newRectF(50, 50, 200, 200);

canvas.drawRoundRect(rect,

30,//x軸的半徑

30,//y軸的半徑

paint);

}

canvas.drawPath:

1

2

3

4

5

6

7

8

9

10

11

12@Override

protected void onDraw(Canvas canvas) {

Path path =newPath();//定義一條路徑

path.moveTo(10, 10);//移動到 坐標10,10

path.lineTo(50, 60);

path.lineTo(200,80);

path.lineTo(10, 10);

canvas.drawPath(path, paint);

}

canvas.drawTextOnPath:

1

2

3

4

5

6

7

8

9

10

11

12

13@Override

protected void onDraw(Canvas canvas) {

Path path =newPath();//定義一條路徑

path.moveTo(10, 10);//移動到 坐標10,10

path.lineTo(50, 60);

path.lineTo(200,80);

path.lineTo(10, 10);

//????????? canvas.drawPath(path, paint);

canvas.drawTextOnPath("Android777開發(fā)者博客", path, 10, 10, paint);

}

位置轉(zhuǎn)換方法,canvas.rorate和canvas.translate:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46@Override

protected void onDraw(Canvas canvas) {

paint.setAntiAlias(true);

paint.setStyle(Style.STROKE);

canvas.translate(canvas.getWidth()/2, 200);//將位置移動畫紙的坐標點:150,150

canvas.drawCircle(0, 0, 100, paint);//畫圓圈

//使用path繪制路徑文字

canvas.save();

canvas.translate(-75, -75);

Path path =newPath();

path.addArc(newRectF(0,0,150,150), -180, 180);

Paint citePaint =newPaint(paint);

citePaint.setTextSize(14);

citePaint.setStrokeWidth(1);

canvas.drawTextOnPath("http://www.android777.com", path, 28, 0, citePaint);

canvas.restore();

Paint tmpPaint =newPaint(paint);//小刻度畫筆對象

tmpPaint.setStrokeWidth(1);

float? y=100;

int count = 60;//總刻度數(shù)

for(int i=0 ; i

if(i%5 == 0){

canvas.drawLine(0f, y, 0, y+12f, paint);

canvas.drawText(String.valueOf(i/5+1), -4f, y+25f, tmpPaint);

}else{

canvas.drawLine(0f, y, 0f, y +5f, tmpPaint);

}

canvas.rotate(360/count,0f,0f);//旋轉(zhuǎn)畫紙

}

//繪制指針

tmpPaint.setColor(Color.GRAY);

tmpPaint.setStrokeWidth(4);

canvas.drawCircle(0, 0, 7, tmpPaint);

tmpPaint.setStyle(Style.FILL);

tmpPaint.setColor(Color.YELLOW);

canvas.drawCircle(0, 0, 5, tmpPaint);

canvas.drawLine(0, 10, 0, -65, paint);

}

上面幾個例子基本已經(jīng)將常用的canvas.draw*方法測試過了,我們結(jié)合一些事件,做一些有用戶交互的應(yīng)用:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67package com.android777.demo.uicontroller.graphics;

import java.util.ArrayList;

import android.app.Activity;

import android.content.Context;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.graphics.PointF;

import android.os.Bundle;

import android.view.MotionEvent;

import android.view.View;

public class CanvasDemoActivity extends Activity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(newCustomView1(this));

}

/**

* 使用內(nèi)部類 自定義一個簡單的View

* @author Administrator

*

*/

class CustomView1 extends View{

Paint paint;

private ArrayList graphics =newArrayList();

PointF point;

public CustomView1(Context context) {

super(context);

paint =newPaint();//設(shè)置一個筆刷大小是3的黃色的畫筆

paint.setColor(Color.YELLOW);

paint.setStrokeJoin(Paint.Join.ROUND);

paint.setStrokeCap(Paint.Cap.ROUND);

paint.setStrokeWidth(3);

}

@Override

public boolean onTouchEvent(MotionEvent event) {

graphics.add(newPointF(event.getX(),event.getY()));

invalidate();//重新繪制區(qū)域

returntrue;

}

//在這里我們將測試canvas提供的繪制圖形方法

@Override

protected void onDraw(Canvas canvas) {

for(PointF point : graphics) {

canvas.drawPoint(point.x, point.y, paint);

}

//????????? super.onDraw(canvas);

}

}

}

當用戶點擊時將出現(xiàn)一個小點,拖動時將畫出一條用細點組成的虛線:

canvas的應(yīng)用

canva還可以制作很多自定義控件,比如google日歷的monthview就是用canvas繪制出來的,github上有很多使用canva的項目,所有的圖表庫都是用canvas繪制的。

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

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

  • ¥開啟¥ 【iAPP實現(xiàn)進入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程,因...
    小菜c閱讀 7,384評論 0 17
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,323評論 25 708
  • 導(dǎo)航 Android Paint之顏色過濾器 Paint之shader(圖像渲染) Paint之PathEffec...
    侯蛋蛋_閱讀 4,898評論 0 5
  • 版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載 前言 Canvas 本意是畫布的意思,然而將它理解為繪制工具一...
    cc榮宣閱讀 41,783評論 1 47
  • 昨晚臨睡前,閨蜜發(fā)了幾張她在老家拍的照片給我,看完后,居然害我一整晚都在夢里刨地瓜。 今早上班,我將照片給同事看,...
    李茗閱讀 1,736評論 27 23

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