Android之Canvas繪制圖形

本文轉(zhuǎn)自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2012/1212/703.html

Android中使用圖形處理引擎鲁驶,2D部分是android SDK內(nèi)部自己提供鉴裹,3D部分是用Open GL ES
1.0。 大部分2D使用的api都在android.graphics和android.graphics.drawable包中。他們提供了圖形處理相關(guān)的:
Canvas径荔、ColorFilter督禽、Point(點(diǎn))和RetcF(矩形)等,還有一些動(dòng)畫相關(guān)的:AnimationDrawable猖凛、
BitmapDrawable和TransitionDrawable等赂蠢。以圖形處理來(lái)說(shuō),我們最常用到的就是在一個(gè)View上畫一些圖片辨泳、形狀或者自定義的文本內(nèi)容虱岂,這里我們都是使用Canvas來(lái)實(shí)現(xiàn)的。你可以獲取View中的Canvas對(duì)象菠红,繪制一些自定義形狀第岖,然后調(diào)用View.
invalidate方法讓View重新刷新,然后繪制一個(gè)新的形狀试溯,這樣達(dá)到2D動(dòng)畫效果蔑滓。

  • 下面我們就主要來(lái)了解下Canvas的使用方法。

Canvas對(duì)象的獲取方式有兩種:一種我們通過(guò)重寫View.onDraw方法遇绞,View中的Canvas對(duì)象會(huì)被當(dāng)做參數(shù)傳遞過(guò)來(lái)键袱,我們操作這個(gè)Canvas,效果會(huì)直接反應(yīng)在View中摹闽。另一種就是當(dāng)你想創(chuàng)建一個(gè)Canvas對(duì)象時(shí)使用的方法:

    Bitmap b = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);    
    Canvas c = new Canvas(b); 

上面代碼創(chuàng)建了一個(gè)尺寸是100*100的Bitmap蹄咖,使用它作為Canvas操作的對(duì)象,這時(shí)候的Canvas就是使用創(chuàng)建的方式付鹿。當(dāng)你使用創(chuàng)建的Canvas在bitmap上執(zhí)行繪制方法后澜汤,你還可以將繪制的結(jié)果提交給另外一個(gè)Canvas,這樣就可以達(dá)到兩個(gè)Canvas協(xié)作完成的效果舵匾,簡(jiǎn)化邏輯俊抵。但是android SDK建議使用View.onDraw參數(shù)里提供的Canvas就好,沒(méi)必要自己創(chuàng)建一個(gè)新的Canvas對(duì)象坐梯。接下來(lái)我們看看Canvas提供我們哪些繪制圖形的方法徽诲。我們創(chuàng)建一個(gè)自定義View對(duì)象,使用onDraw方法提供的Canvas進(jìn)行繪制圖形吵血。

MyCustomView.java:

public class MyCustomView extends View { 
 
    private Paint paint; 
 
    public MyCustomView(Context context, AttributeSet attrs) { 
        super(context, attrs); 
    } 
 
    public MyCustomView(Context context) { 
        super(context); 
        paint = new Paint(); // 設(shè)置一個(gè)筆刷大小是3的黃色的畫筆 
        paint.setColor(Color.YELLOW); 
        paint.setStrokeJoin(Paint.Join.ROUND); 
        paint.setStrokeCap(Paint.Cap.ROUND); 
        paint.setStrokeWidth(3); 
    } 
 
    @Override 
    protected void onDraw(Canvas canvas) { 
        // TODO Auto-generated method stub 
        super.onDraw(canvas); 
    } 
} 
activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    android:id="@+id/main_root_ll" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical" > 
 
    <com.example.testcustomview.MyCustomView 
        android:id="@+id/custom_view" 
        android:layout_width="match_parent" 
        android:layout_height="match_parent" /> 
 
</LinearLayout> 
image.png

運(yùn)行發(fā)現(xiàn)一片空白馏段,因?yàn)樵谧远x的MyCustomView中,我們沒(méi)有做任何的繪制操作践瓷。canvas提供的繪制圖形的方法都是以draw開頭的院喜,我們可以查看api:
enter description here
從上面方法的名字看來(lái)我們可以知道Canvas可以繪制的對(duì)象有:

arcs 弧線
argb和color 填充顏色
Bitmap 位圖
circle和oval 圓
point 點(diǎn)
line 線
Rect 矩形
Picture 圖片
RoundRect 圓角矩形
text 文本
Vertices 頂點(diǎn)
path 路徑

通過(guò)組合這些對(duì)象我們可以畫出一些簡(jiǎn)單有趣的界面出來(lái),但是光有這些功能還是不夠的晕翠,如果我要畫一個(gè)儀表盤(數(shù)字圍繞顯示在一個(gè)圓圈中)呢喷舀? 幸好Android還提供了一些對(duì)Canvas位置轉(zhuǎn)換的方法:rorate砍濒、scale、translate硫麻、skew(扭曲)等爸邢,而且它允許你通過(guò)獲得它的轉(zhuǎn)換矩陣對(duì)象直接操作它。這些操作就像是雖然你的筆還是原來(lái)的地方畫拿愧,但是畫紙旋轉(zhuǎn)或者移動(dòng)了杠河,所以你畫的東西的方位就產(chǎn)生變化。為了方便一些轉(zhuǎn)換操作浇辜,Canvas還提供了保存和回滾屬性的方法(save和restore)券敌,比如你可以先保存目前畫紙的位置(save),然后旋轉(zhuǎn)90度柳洋,向下移動(dòng)100像素后畫一些圖形待诅,畫完后調(diào)用restore方法返回到剛才保存的位置。下面我們就演示下canvas的一些簡(jiǎn)單用法:

一些簡(jiǎn)單用法

protected void onDraw(Canvas canvas) {   
    canvas.drawCircle(100, 100, 90, paint);    
} 

效果是:


image.png
@Override    
protected void onDraw(Canvas canvas) { 
    //繪制弧線區(qū)域 
    RectF rect = new RectF(0, 0, 100, 100);                                     
    canvas.drawArc(rect, //弧線所使用的矩形區(qū)域大小    
            0,  //開始角度    
            90, //掃過(guò)的角度    
            false, //是否使用中心    
            paint); 
} 

效果是:


image.png
protected void onDraw(Canvas canvas) {    
    //繪制弧線區(qū)域    
    RectF rect = new RectF(0, 0, 100, 100);    
    canvas.drawArc(rect, //弧線所使用的矩形區(qū)域大小    
            0,  //開始角度    
            90, //掃過(guò)的角度    
            true, //是否使用中心    
            paint);    
} 

效果是:


image.png

兩圖對(duì)比我們可以發(fā)現(xiàn)熊镣,當(dāng) drawArcs(rect,startAngel,sweepAngel,useCenter,paint)中的useCenter為false時(shí)卑雁,弧線區(qū)域是用弧線開始角度和結(jié)束角度直接連接起來(lái)的,當(dāng)useCenter為true時(shí)绪囱,是弧線開始角度和結(jié)束角度都與中心點(diǎn)連接测蹲,形成一個(gè)扇形。

protected void onDraw(Canvas canvas) {    
    canvas.drawColor(Color.BLUE);    
} 

效果是:


image.png

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

@Override    
protected void onDraw(Canvas canvas) {    
    //畫一條線    
    canvas.drawLine(10, 10, 100, 100, paint);    
} 

效果是:


image.png
@Override    
protected void onDraw(Canvas canvas) {    
    //定義一個(gè)矩形區(qū)域    
    RectF oval = new RectF(0,0,200,300);    
    //矩形區(qū)域內(nèi)切橢圓    
    canvas.drawOval(oval, paint);    
} 

效果是:


image.png
@Override    
protected void onDraw(Canvas canvas) {    
    //按照既定點(diǎn) 繪制文本內(nèi)容    
    canvas.drawPosText("Android777", new float[]{    
            10,10, //第一個(gè)字母在坐標(biāo)10,10    
            20,20, //第二個(gè)字母在坐標(biāo)20,20    
            30,30, //....    
            40,40,    
            50,50,    
            60,60,    
            70,70,    
            80,80,    
            90,90,    
            100,100    
    }, paint);    
} 

效果是:


image.png
@Override    
    protected void onDraw(Canvas canvas) {    
        RectF rect = new RectF(50, 50, 200, 200);    
        canvas.drawRect(rect, paint);    
    }    
} 

效果是:


image.png
@Override    
protected void onDraw(Canvas canvas) {    
    RectF rect = new RectF(50, 50, 200, 200);    
    canvas.drawRoundRect(rect,    
                        30, //x軸的半徑    
                        30, //y軸的半徑    
                        paint);    
} 

效果是:


image.png
@Override    
protected void onDraw(Canvas canvas) {    
    Path path = new Path(); //定義一條路徑    
    path.moveTo(10, 10); //移動(dòng)到 坐標(biāo)10,10    
    path.lineTo(50, 60);    
    path.lineTo(200,80);    
    path.lineTo(10, 10);    
    canvas.drawPath(path, paint);    
} 

效果是:


image.png
@Override    
        protected void onDraw(Canvas canvas) {    
            Path path = new Path(); //定義一條路徑    
            path.moveTo(10, 10); //移動(dòng)到 坐標(biāo)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);    
        } 

效果是:


image.png
  • Canvas的其他方法

canvas.save 用來(lái)保存Canvas的狀態(tài)弛房。save之后,可以調(diào)用Canvas的平移而柑、放縮、旋轉(zhuǎn)荷逞、錯(cuò)切媒咳、裁剪等操作。

canvas.restore 用來(lái)恢復(fù)Canvas之前保存的狀態(tài)种远。防止save后對(duì)Canvas執(zhí)行的操作對(duì)后續(xù)的繪制有影響涩澡。

canvas.translate(x,y) 平移,將畫布的坐標(biāo)原點(diǎn)向左右方向移動(dòng)x坠敷,向上下方向移動(dòng)y;canvas的默認(rèn)位置是在(0,0)

canvas.rotate 旋轉(zhuǎn)妙同,將畫布以圓心為圓點(diǎn)旋轉(zhuǎn)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市膝迎,隨后出現(xiàn)的幾起案子粥帚,更是在濱河造成了極大的恐慌限次,老刑警劉巖费尽,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡长豁,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事∽茨” “怎么了拌汇?”我有些...
    開封第一講書人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我貌嫡,道長(zhǎng),這世上最難降的妖魔是什么夫椭? 我笑而不...
    開封第一講書人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上洞豁,老公的妹妹穿的比我還像新娘。我一直安慰自己溪北,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開白布咧叭。 她就那樣靜靜地躺著蚀乔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪菲茬。 梳的紋絲不亂的頭發(fā)上吉挣,一...
    開封第一講書人閱讀 52,156評(píng)論 1 308
  • 那天派撕,我揣著相機(jī)與錄音,去河邊找鬼睬魂。 笑死终吼,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的氯哮。 我是一名探鬼主播际跪,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼喉钢!你這毒婦竟也來(lái)了姆打?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤肠虽,失蹤者是張志新(化名)和其女友劉穎幔戏,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體税课,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡帽哑,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了竟纳。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片更哄。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖啸如,靈堂內(nèi)的尸體忽然破棺而出侍匙,到底是詐尸還是另有隱情,我是刑警寧澤叮雳,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布想暗,位于F島的核電站,受9級(jí)特大地震影響帘不,放射性物質(zhì)發(fā)生泄漏说莫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一寞焙、第九天 我趴在偏房一處隱蔽的房頂上張望储狭。 院中可真熱鬧,春花似錦捣郊、人聲如沸辽狈。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)刮萌。三九已至,卻和暖如春娘扩,著一層夾襖步出監(jiān)牢的瞬間着茸,已是汗流浹背壮锻。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留涮阔,地道東北人猜绣。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像澎语,于是被迫代替她去往敵國(guó)和親途事。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容