自定義控件(一)

最近在跟扔物線大嬸學(xué)自定義控件,其實(shí)許多東西之前都用過(guò)的氯迂,不過(guò)時(shí)間長(zhǎng)就忘了践叠,然后這次就系統(tǒng)的復(fù)習(xí)一下,順便記錄下來(lái)嚼蚀。
自定義繪制禁灼,首先要?jiǎng)?chuàng)建好Paint對(duì)象,重寫(xiě)onDraw()轿曙,把繪制代碼寫(xiě)在onDraw()里匾二,這就是自定義繪制最基本的實(shí)現(xiàn)。Paint和canvas組合使用可以畫(huà)出各種各樣的圖形拳芙。

Paint類的常用方法

  • paint.setStyle(Style style) 設(shè)置繪制模式
  • paint.setColor(int color) 設(shè)置顏色
  • paint.setStrokeWidth(float width) 設(shè)置線條寬度
  • paint.setTextSize(float textSize) 設(shè)置文字大小
  • paint.setAntiAlias(boolean aa) 設(shè)置抗鋸齒開(kāi)關(guān)(初始化Paint時(shí)可直接設(shè)置)

paint.setStyle(Style style)主要有三種樣式:FILL,STROKE和FILL_AND_STROKE察藐。FILL 是填充模式,STROKE 是畫(huà)線模式(即勾邊模式)舟扎,F(xiàn)ILL_AND_STROKE 是兩種模式一并使用:既畫(huà)線又填充分飞。它的默認(rèn)值是 FILL,填充模式睹限。

1.canvas.drawColor()顏色填充

這算是最簡(jiǎn)單的了譬猫,直接canvas.drawColor(Color.Yellow)。類似的方法還有drawColor(Color.parse("")),直接填16進(jìn)制色值就行羡疗,例如drawColor(Color.parse("#F00")),drawColor(Color.parse("#6F00")),drawColor(Color.parse("#CCCCCC")),drawColor(Color.parse("#88880000"))染服。 drawRGB(int r, int g, int b),drawARGB(int a, int r, int g, int b)
drawColor()
    canvas.drawColor(Color.YELLOW);

2.canvas.drawCircle(float centerX, float centerY, float radius, Paint paint)畫(huà)圓

前兩個(gè)參數(shù)表示圓的圓心坐標(biāo)叨恨,radius是圓心半徑柳刮,paint可以設(shè)置圓的填充顏色,空心圓還是實(shí)心圓還是圓環(huán)痒钝,還有圓環(huán)的寬度等(插一句秉颗,從屏幕左上角,向右為X軸正方向送矩,向下為Y軸正方向)


drawCircle()
        //實(shí)心圓
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);//開(kāi)啟抗鋸齒
        paint.setColor(Color.BLACK);
        paint.setStyle(Paint.Style.FILL);
        canvas.drawCircle(200,200, 150, paint);
        //空心圓
        paint.setStyle(Paint.Style.STROKE);
        canvas.drawCircle(700, 200, 150, paint);
        //藍(lán)色實(shí)心圓
        paint.setColor(Color.BLUE);
        paint.setStyle(Paint.Style.FILL);
        canvas.drawCircle(700, 600, 150, paint);
        //空心圓環(huán)蚕甥,環(huán)寬20
        paint.setStrokeWidth(20);
        canvas.drawCircle(200, 600, 150, paint);

3.canvas.drawRect(float left, float top, float right, float bottom, Paint paint)畫(huà)矩形

drawRect()
canvas.drawRect(100,100,400,300,paint);

從上面可以很明顯的看到各個(gè)參數(shù)所代表的意思。矩形的width = right-left栋荸,矩形的hight = bottom-top菇怀。當(dāng)寬和高相等時(shí)就是正方形。例如晌块,我要畫(huà)一個(gè)寬為300爱沟,高為200的矩形,是這樣的canvas.drawRect(100,100,400,300,paint)

4.canvas.drawPoint(float x, float y, Paint paint)畫(huà)點(diǎn)

x 和 y 是點(diǎn)的坐標(biāo)摸袁。點(diǎn)的大小可以通過(guò) paint.setStrokeWidth(width) 來(lái)設(shè)置钥顽;點(diǎn)的形狀可以通過(guò) paint.setStrokeCap(cap) 來(lái)設(shè)置:ROUND 畫(huà)出來(lái)是圓形的點(diǎn)义屏,SQUARE 或 BUTT 畫(huà)出來(lái)是方形的點(diǎn)靠汁。


drawPoint()
        //圓點(diǎn)
        paint.setColor(Color.BLACK);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStrokeWidth(60);
        canvas.drawPoint(200, 200, paint);
        方點(diǎn)
        paint.setStrokeCap(Paint.Cap.SQUARE);
        paint.setStrokeWidth(60);
        canvas.drawPoint(500,200,paint);

drawPoint()是畫(huà)單個(gè)點(diǎn)蜂大,還有兩個(gè)方法是批量畫(huà)點(diǎn),drawPoints(float[] pts, int offset, int count, Paint paint) / drawPoints(float[] pts, Paint paint)蝶怔,

float[] points = {0, 0, 50, 50, 50, 100, 100, 50, 100, 100, 150, 50, 150, 100};每?jī)蓚€(gè)數(shù)字為一個(gè)點(diǎn)

// 繪制四個(gè)點(diǎn):(50, 50) (50, 100) (100, 50) (100, 100)
canvas.drawPoints(points, 2 /* 跳過(guò)兩個(gè)數(shù)奶浦,即前兩個(gè) 0 */, 4 /* 坐標(biāo)個(gè)數(shù),也就是兩個(gè)點(diǎn)*/, paint);
//繪制所有的點(diǎn)
canvas.drawPoints(points,paint);

5.canvas.drawOval(float left, float top, float right, float bottom, Paint paint)畫(huà)橢圓

left, top, right, bottom 是這個(gè)橢圓的左踢星、上澳叉、右、下四個(gè)邊界點(diǎn)的坐標(biāo)


draw.Oval()
//實(shí)心橢圓
paint.setStyle(Style.FILL);
canvas.drawOval(50, 50, 350, 200, paint);
//空心橢圓
paint.setStyle(Style.STROKE);
canvas.drawOval(400, 50, 700, 200, paint);

6.canvas.drawLine(float startX, float startY, float stopX, float stopY, Paint paint)畫(huà)線

前兩個(gè)參數(shù)是線的起點(diǎn)坐標(biāo)沐悦,然后兩個(gè)是終點(diǎn)坐標(biāo)成洗。


drawLine()
paint.setStrokeWidth(20);//設(shè)置線寬
canvas.drawLine(100, 100, 600, 500, paint);paint

畫(huà)線跟畫(huà)點(diǎn)類似,也有批量畫(huà)線的方法drawLines(float[] pts, int offset, int count, Paint paint) / drawLines(float[] pts, Paint paint)

float[] points = {20, 20, 120, 20, 70, 20, 70, 120, 20, 120, 120, 120, 150, 20, 250, 20, 150, 20, 150, 120, 250, 20, 250, 120, 150, 120, 250, 120};
canvas.drawLines(points, paint);  //畫(huà)所有線
canvas.drawPoints(points, 2 /* 跳過(guò)兩條線藏否,即4個(gè)點(diǎn)瓶殃,8個(gè)數(shù)字 */, 3 /* 一共繪制三個(gè)點(diǎn)*/, paint);

7.canvas.drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, Paint paint)畫(huà)圓角矩形

left, top, right, bottom 是四條邊的坐標(biāo),rx 和 ry 是圓角的橫向半徑和縱向半徑副签。


drawRoundRect()
//實(shí)心圓角矩形
canvas.drawRoundRect(100,100,600,300,30,30,paint);(設(shè)置paint填充模式可畫(huà)空心圓角矩形)

8.canvas.drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, Paint paint) 繪制弧形或扇形

drawArc() 是使用一個(gè)橢圓來(lái)描述弧形的遥椿。left, top, right, bottom 描述的是這個(gè)弧形所在的橢圓;startAngle 是弧形的起始角度(x 軸的正向淆储,即正右的方向冠场,是 0 度的位置;順時(shí)針為正角度本砰,逆時(shí)針為負(fù)角度)碴裙,sweepAngle 是弧形劃過(guò)的角度;useCenter 表示是否連接到圓心点额,如果不連接到圓心青团,就是弧形,如果連接到圓心咖楣,就是扇形督笆。


drawArc()
paint.setStyle(Paint.Style.FILL); // 填充模式
canvas.drawArc(200, 100, 800, 500, -110, 100, true, paint); // 繪制扇形
canvas.drawArc(200, 100, 800, 500, 20, 140, false, paint); // 繪制弧形
paint.setStyle(Paint.Style.STROKE); // 畫(huà)線模式
canvas.drawArc(200, 100, 800, 500, 180, 60, false, paint); // 繪制不封口的弧形

9.canvas.drawPath(Path path, Paint paint) 畫(huà)自定義圖形(重點(diǎn)來(lái)了)

Path 可以描述直線、二次曲線诱贿、三次曲線娃肿、圓、橢圓珠十、弧形料扰、矩形、圓角矩形焙蹭。把這些圖形結(jié)合起來(lái)晒杈,就可以描述出很多復(fù)雜的圖形。Path 有兩類方法孔厉,一類是直接描述路徑的拯钻,另一類是輔助的設(shè)置或計(jì)算帖努。(詳細(xì)解釋請(qǐng)點(diǎn)這里
下面來(lái)重點(diǎn)分析下這個(gè)心形是怎么畫(huà)的

drawPath()

      Path path = new Path(); // 初始化 Path 對(duì)象
      //第一步,path添加左邊一個(gè)扇形
      path.addArc(200, 200, 400, 400, -225, 225);
      //第二步粪般,從第一步完成的地方添加右邊的扇形
      path.arcTo(400, 200, 600, 400, -180, 225, false);
      //第三步拼余,從第二部步結(jié)束的地方畫(huà)線,到點(diǎn)(400,542)也就是心形最下面的點(diǎn)亩歹,并與起點(diǎn)封閉封閉
      path.lineTo(400, 542);
      //畫(huà)圖
      canvas.drawPath(path, paint);

path可以添加各種形狀匙监,然后相互連接起來(lái)。


path

path

更多的方法小作,大家可以自己研究研究亭姥。

10.canvas.drawBitmap(Bitmap bitmap, float left, float top, Paint paint) 畫(huà) Bitmap

繪制 Bitmap 對(duì)象,也就是把這個(gè) Bitmap 中的像素內(nèi)容貼過(guò)來(lái)顾稀。其中 left 和 top 是要把 bitmap 繪制到的位置坐標(biāo)致份。

canvas.drawBitmap(bitmap, 200, 100, paint);

11.canvas.drawText(String text, float x, float y, Paint paint) 繪制文字

界面里所有的顯示內(nèi)容,都是繪制出來(lái)的础拨,包括文字氮块。 drawText() 這個(gè)方法就是用來(lái)繪制文字的。參數(shù) text 是用來(lái)繪制的字符串诡宗,x 和 y 是繪制的起點(diǎn)坐標(biāo)滔蝉。
通過(guò) Paint.setTextSize(textSize),可以設(shè)置文字的大小塔沃。

paint.setTextSize(18);
canvas.drawText(text, 100, 25, paint);
paint.setTextSize(36);
canvas.drawText(text, 100, 70, paint);

12.畫(huà)柱狀圖和餅圖

練習(xí)

這些復(fù)雜的圖形其實(shí)就是把前面講到的方法綜合起來(lái)用就可以繪制成想要的圖形了蝠引。把一些基本的封裝起來(lái),再把一些可以設(shè)置值和顏色的方法暴露出去蛀柴,就成了自己的自定義控件螃概。

推薦兩個(gè)圖表類的開(kāi)源項(xiàng)目,一個(gè)android的MPAndroidChart,一個(gè)h5頁(yè)面上可以用的ECharts鸽疾。

以上所有的代碼在這里

另外強(qiáng)烈推薦大家關(guān)注下扔物線大神的公眾號(hào)吊洼,這是一個(gè)系列的教程,每周一篇制肮。

扔物線大嬸公眾號(hào)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末冒窍,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子豺鼻,更是在濱河造成了極大的恐慌综液,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,820評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件儒飒,死亡現(xiàn)場(chǎng)離奇詭異谬莹,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)附帽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)埠戳,“玉大人,你說(shuō)我怎么就攤上這事士葫∑蚨” “怎么了送悔?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,324評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵慢显,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我欠啤,道長(zhǎng)荚藻,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,714評(píng)論 1 297
  • 正文 為了忘掉前任洁段,我火速辦了婚禮应狱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘祠丝。我一直安慰自己疾呻,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布写半。 她就那樣靜靜地躺著岸蜗,像睡著了一般。 火紅的嫁衣襯著肌膚如雪叠蝇。 梳的紋絲不亂的頭發(fā)上璃岳,一...
    開(kāi)封第一講書(shū)人閱讀 52,328評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音悔捶,去河邊找鬼铃慷。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蜕该,可吹牛的內(nèi)容都是我干的犁柜。 我是一名探鬼主播,決...
    沈念sama閱讀 40,897評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼堂淡,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼赁温!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起淤齐,我...
    開(kāi)封第一講書(shū)人閱讀 39,804評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤股囊,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后更啄,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體稚疹,經(jīng)...
    沈念sama閱讀 46,345評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了内狗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片怪嫌。...
    茶點(diǎn)故事閱讀 40,561評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖柳沙,靈堂內(nèi)的尸體忽然破棺而出岩灭,到底是詐尸還是另有隱情,我是刑警寧澤赂鲤,帶...
    沈念sama閱讀 36,238評(píng)論 5 350
  • 正文 年R本政府宣布噪径,位于F島的核電站,受9級(jí)特大地震影響数初,放射性物質(zhì)發(fā)生泄漏找爱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評(píng)論 3 334
  • 文/蒙蒙 一泡孩、第九天 我趴在偏房一處隱蔽的房頂上張望车摄。 院中可真熱鬧,春花似錦仑鸥、人聲如沸吮播。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,417評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)意狠。三九已至,卻和暖如春泵琳,著一層夾襖步出監(jiān)牢的瞬間摄职,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,528評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工获列, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留谷市,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,983評(píng)論 3 376
  • 正文 我出身青樓击孩,卻偏偏與公主長(zhǎng)得像迫悠,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子巩梢,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評(píng)論 2 359

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