自定義View ——Canvas之繪制基本形狀

自定義View ——Canvas之繪制基本形狀##

轉載出處:http://www.gcssloop.com/customview/Canvas_Convert/

一.Canvas簡介###

Canvas 稱之為畫布,是安卓平臺2D圖形繪制的基礎姑廉,非常強大。

一般來說,比較基礎的東西有兩大特點:

1.可操作性強:由于這些是構成上層的基礎景用,所以可操作性必然十分強大。

2.比較難用:各種方法太過基礎惭蹂,想要完美的將這些操作組合起來有一定難度伞插。

本系列文章不僅會介紹到Canvas的操作方法,還會簡單介紹一些設計思路和技巧盾碗。

二.Canvas的常用操作速查表##

列表:

操作類型 相關API 備注
繪制顏色 drawColor,drawRGB,drawARGB 使用單一顏色填充整個畫布
繪制基本形狀 drawPoint,drawPoints,drawLine,drawLines,drawRect,drawRountRect,drawOval,drawCircle,drawArc 依次為點媚污、線、矩形廷雅、圓角矩形耗美、橢圓、圓航缀、圓弧
繪制圖片 drawBitmap,drawPicture 繪制位圖和圖片
繪制文本 drawText,drawPosText,drawTextOnPath 依次為 繪制文字商架、繪制文字時指定每個文字位置、根據路徑繪制文字
頂點操作 drawVertices,drawBitmapMesh 通過對頂點操作可以使圖像形變芥玉,drawVertices直接對畫布作用蛇摸、drawBitmapMesh只對繪制的Bitmap作用
繪制路徑 drawPath 繪制路徑,繪制貝塞爾曲線時也需要用該函數
畫布剪裁 clipPath,clipRect 設置畫布的顯示區(qū)域
畫布快照 save,restore,saveLayerXxx,restoreToCount,getSaveCount 依次為保存當前狀態(tài)灿巧、回滾到上一次保存的狀態(tài)赶袄、保存圖層狀態(tài)揽涮、回滾到指定狀態(tài)、獲取保存次數
畫布變換 translate,scale,rotate,skew 依次為位移弃鸦、縮放绞吁、旋轉、錯切
Matrix矩陣 getMatrix唬格、setMatrix家破、concat 實際畫布的位移,縮放等操作的都是圖像矩陣Matrix购岗,只不過Matrix比較難以理解和使用汰聋,故封裝了一些常用的方法。

三喊积、Canvas詳解###

本篇內容主要講解如何利用Canvas繪制基本圖形烹困。

繪制顏色:

繪制顏色是填充整個畫布,常用于繪制底色乾吻。

代碼:

canvas.drawColor(Color.BLUE);//繪制藍色

如圖:

創(chuàng)建畫筆:

想繪制內容髓梅,首先需要先創(chuàng)建一個畫筆,如下:
//創(chuàng)建一個畫筆
private Paint mPaint=new Paint();
//初始化畫筆
private void initPaint(){
mPaint.setColor(Color.BLACK); //設置畫筆顏色
mPaint.setStyle(Paint.Style.FILL); //設置畫筆模式為填充
mPaint.setStrokeWidth(10f); //設置畫筆寬度為10px
}
//在構造函數中初始化
public SloopView(Context context,AttributeSet attrs){
super(context,attrs);
initPaint();
}

在創(chuàng)建完畫筆之后绎签,就可以在Canvas中繪制各種內容了枯饿。


繪制點:###

可以繪制一個點,也可以繪制一組點诡必,如下:

canvas.drawPoint(200,200,mPaint);
canvas.drawPoints(new float[]{
    500,500,
    500,600,
    500,700
},mPaint);

關于坐標原點默認在左上角奢方,水平向右為x軸增大方向,豎直向下為y軸增大方向爸舒。

繪制直線:###

繪制直線只需要兩個點蟋字,初始點和結束點,同樣繪制直線也可以繪制一條或者繪制一組:

canvas.drawLine(300,300,500,500,mPaint);//在坐標(300,300)(500,600)之間繪制一條直線
canvas.drawLines(new float[]{            //繪制一組線  每四位數字(兩個點的坐標)確定一條線
100,200,200,200,
100,300,200,200
},mpaint);

繪制矩形:###

確定確定一個矩形最少需要四個數據扭勉,就是對角線的兩個點的坐標值鹊奖,這里一般采用左上角和右下角的兩個點的坐標。

關于繪制矩形剖效,Canvas提供了三種重載方法嫉入,第一種就是提供四個數值(矩形左上角和右下角兩個點的坐標)來確定一個矩形進行繪制。其余兩種是先將矩形封裝為Rect或者RectF(實際上仍然是用兩個坐標點來確定的矩形)璧尸,然后傳遞給Canvas繪制咒林,如下:
//第一種
canvas.drawRect(100,100,800,400,mPaint);
//第二種
Rect mRect=new Rect(100,100,800,400);
canvas.drawRect(mRect,mPaint);
//第三種
RectF mRectF=new RectF(100,100,800,400);
canvas.drawRect(mRectF,mPaint);

三種繪制的結果是完全一樣的。


繪制圓角矩形###

繪制圓角矩形也提供了兩種重載方式爷光,如下:
//第一種
RectF mRectF=new RectF(100,100,800,400);
canvas.drawRoundRect(mRectF,30,30,mPaint);
//第二種
canvas.drawRoundRect(100,100,800,400,30,30,mPaint);

第二種方法在API21的時候才添加上垫竞,所以我們一般使用的都是第一種。


與矩形相比,圓角矩形多出來了兩個參數rx和ry欢瞪,這里圓角矩形的角實際上不是一個正圓的圓弧活烙,而是橢圓的圓弧,這里的兩個參數實際上是橢圓的兩個半徑遣鼓,他們看起來如下圖:


紅線標注的rx與ry就是兩個半徑啸盏,也就是相比繪制矩形多出來的那兩個參數。

我們了解到原理后骑祟,就可以為所欲為了回懦,通過計算可知我們上次繪制的矩形寬度為700,高度為300次企,當你讓rx大于350(寬度的一半)怯晕,ry大于150(高度的一半)時奇跡就出現了,你會發(fā)現圓角矩形變成了一個橢圓缸棵,他們畫出來是這樣的(為了方便確認我更改了畫筆顏色舟茶,同時繪制出了矩形和圓角矩形):

//矩形
RectF  mRectF=new RectF(100,100,800,400);
//繪制背景矩形
mPaint.setColor(Color.GRAY);
canvas.drawRect(mRectF,mPaint);
//繪制圓角矩形
mPaint.setColor(Color.BLUE);
canvas.drawRoundRect(mRectF,700,400,mPaint);

其中灰色部分是我們所選定的矩形,而里面的圓角矩形則變成了一個橢圓堵第,實際上rx為寬度的一半吧凉,ry為高度的一半時,剛好是一個橢圓踏志,通過上面我們分析的原理推算一下就能得到客燕,而當rx大于寬度的一半,ry大于高度的一半時狰贯,實際上是無法計算出圓弧的,所以drawRoundRect對大于該數值的參數進行了限制赏廓,凡是大于一半的參數均按照一半來處理涵紊。

繪制橢圓:###

相對于繪制圓角矩形,繪制橢圓就簡單的多了幔摸,因為他只需要一個矩形作為參數:

//第一種
RectF  rectF=new RectF(100,100,800,400);
canvas.drawOval(rectF,mPaint);
//第二種
canvas.drawOval(100,100,800,400,mPaint);

以上兩種方法效果完全一樣视乐,但一般使用第一種分蓖。


繪制橢圓實際上就是繪制一個矩形的內切圖形,原理如下:

繪制圓:###

如下:

canvas.drawCircle(500,500,400,mPaint);//繪制一個圓心坐標在(500,500),半徑為400的圓疮蹦。

繪制圓形有四個參數,前兩個是圓心坐標前硫,第三個是半徑淮野,最后一個是畫筆。


繪制圓豢林ā:

// 第一種
public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter, @NonNull Paint paint){}

// 第二種
public void drawArc(float left, float top, float right, float bottom, float startAngle,
        float sweepAngle, boolean useCenter, @NonNull Paint paint) {}

從上面可以看出酪术,相比于繪制橢圓,繪制圓弧還多了三個參數:

startAngle //開始角度
sweepAngle    //掃過角度
useCenter    //是否使用中心

上代碼:

RectF rectF = new RectF(100,100,800,400);
// 繪制背景矩形
mPaint.setColor(Color.GRAY);
canvas.drawRect(rectF,mPaint);

// 繪制圓弧
mPaint.setColor(Color.BLUE);
canvas.drawArc(rectF,0,90,false,mPaint);

//-------------------------------------

RectF rectF2 = new RectF(100,600,800,900);
// 繪制背景矩形
mPaint.setColor(Color.GRAY);
canvas.drawRect(rectF2,mPaint);

// 繪制圓弧
mPaint.setColor(Color.BLUE);
canvas.drawArc(rectF2,0,90,true,mPaint);

上述代碼實際上是繪制了一個起始角度為0度,掃過90度的圓弧绘雁,兩者的區(qū)別就是是否使用了中心點橡疼,結果如下:

相比于使用橢圓,我們還是使用正圓比較多的庐舟,使用正圓展示一下效果:

RectF  rectF= new RectF(100,100,800,400);
//繪制背景矩形
mPaint.setColor(Color.GRAY);
canvas.drawRect(rectF,mPaint);
//繪制圓弧
mPaint.setColor(Color.BLUE);
canvas.drawArc(rectF,0,90,false,mPaint); 
//-----------------------------------------------------

RectF  rectF2= new RectF(100,600,800,900);
//繪制背景矩形
mPaint.setColor(Color.GRAY);
canvas.drawRect(rectF2,mPaint);
//繪制圓弧
mPaint.setColor(Color.BLUE);
canvas.drawArc(rectF2,0,90,true,mPaint);

簡要介紹Paint###

看了上面這么多欣除,相信有一部分人會產生一個疑問,如果我想繪制一個圓挪略,只要邊不要里面的顏色怎么辦历帚?

很簡單,繪制的基本形狀由Canvas確定瘟檩,但繪制出來的顏色抹缕,具體效果則由Paint確定。

    mPaint.setStyle(Paint.Style.FILL);//設置畫筆模式為填充

為了展示方便墨辛,容易看出效果卓研,之前使用的模式一直為填充模式,實際上畫筆有三種模式睹簇,如下:
STROKE //描邊
FILL //填充
FILL_AND_STROKE //描邊加填充

為了區(qū)分三者效果我們做如下實驗:

    Paint paint = new Paint();
    paint.setColor(Color.BLUE);
    paint.setStrokeWidth(40);

    //描邊
    paint.setStyle(Paint.Style.STROKE);
    canvas.drawCircle(200,200,100,paint);

    //填充
    paint.setStyle(Paint.Style.FILL);
    canvas.drawCircle(200,500,100,paint);
    
    //描邊加填充
    paint.setStyle(Paint.Style.FILL_AND_STROKE);
    canvas.drawCircle(200,800,100,paint);

如果想系統(tǒng)學習自定義View奏赘,推薦看作者GcsSloop系列文章###

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市太惠,隨后出現的幾起案子磨淌,更是在濱河造成了極大的恐慌,老刑警劉巖凿渊,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件梁只,死亡現場離奇詭異,居然都是意外死亡埃脏,警方通過查閱死者的電腦和手機搪锣,發(fā)現死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來彩掐,“玉大人构舟,你說我怎么就攤上這事《掠模” “怎么了狗超?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長朴下。 經常有香客問我努咐,道長,這世上最難降的妖魔是什么桐猬? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任麦撵,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘免胃。我一直安慰自己音五,他們只是感情好,可當我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布羔沙。 她就那樣靜靜地躺著躺涝,像睡著了一般。 火紅的嫁衣襯著肌膚如雪扼雏。 梳的紋絲不亂的頭發(fā)上坚嗜,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天,我揣著相機與錄音诗充,去河邊找鬼苍蔬。 笑死,一個胖子當著我的面吹牛蝴蜓,可吹牛的內容都是我干的碟绑。 我是一名探鬼主播,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼茎匠,長吁一口氣:“原來是場噩夢啊……” “哼格仲!你這毒婦竟也來了?” 一聲冷哼從身側響起诵冒,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤凯肋,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后汽馋,有當地人在樹林里發(fā)現了一具尸體侮东,經...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年豹芯,在試婚紗的時候發(fā)現自己被綠了苗桂。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡告组,死狀恐怖,靈堂內的尸體忽然破棺而出癌佩,到底是詐尸還是另有隱情木缝,我是刑警寧澤,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布围辙,位于F島的核電站我碟,受9級特大地震影響,放射性物質發(fā)生泄漏姚建。R本人自食惡果不足惜矫俺,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧厘托,春花似錦友雳、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至包斑,卻和暖如春流礁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背罗丰。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工神帅, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人萌抵。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓找御,卻偏偏與公主長得像,于是被迫代替她去往敵國和親谜嫉。 傳聞我的和親對象是個殘疾皇子萎坷,可洞房花燭夜當晚...
    茶點故事閱讀 44,619評論 2 354

推薦閱讀更多精彩內容