1:畫(huà)圓
canvas.drawCircle(width / 2, height / 2, radius, mPaint);//繪制圓形,第一個(gè)參數(shù)是圓心的x坐標(biāo),第二個(gè)參數(shù)是圓心的y坐標(biāo),第三個(gè)參數(shù)是半徑,單位都是像素
2:畫(huà)矩形canvas.drawRect(0,0,getMeasuredWidth(),getMeasuredHeight(),paint);//這里繪制出來(lái)的矩形是實(shí)心的矩形,而不是空心的矩形線條,因?yàn)閜aint設(shè)置的style是Paint.Style.FILL,前四個(gè)參數(shù)的具體含義請(qǐng)看下圖

3:canvas.save()和canvas.restore()的區(qū)別
@Override
protected void onDraw(Canvas canvas) {
canvas.drawRect(0,0,getMeasuredWidth(),getMeasuredHeight(),paint);
canvas.drawRect(10,10,getMeasuredWidth()-10,getMeasuredHeight()-10,paint1);
canvas.save();
canvas.translate(10,0);
canvas.restore();
super.onDraw(canvas);
}
區(qū)別是:當(dāng)調(diào)用save方法后,就將canvas的位置和角度記錄下來(lái)了,然后接下來(lái)就可以進(jìn)行畫(huà)布的平移,旋轉(zhuǎn)之類(lèi)的位置變化操作,也可以進(jìn)行畫(huà)圖操作,不過(guò)此時(shí)所畫(huà)的圖是在進(jìn)行了位置變化操作之后的canvas上進(jìn)行的,如果要還原上一次保存的canvas的位置的話,就調(diào)用restore方法,這時(shí)canvas的位置就回到了上一次save時(shí)的狀態(tài)了。
4,畫(huà)圓?。篸rawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)
oval :指定圓弧的外輪廓矩形區(qū)域。
startAngle: 圓弧起始角度(x軸的正右的方向,是0度的位置),單位為度。
sweepAngle: 圓弧掃過(guò)的角度,順時(shí)針?lè)较驗(yàn)檎嵌?,單位為?br> useCenter: 如果為T(mén)rue時(shí),用來(lái)繪制扇形,如果為false時(shí),用來(lái)繪制弧形。
paint: 繪制圓弧的畫(huà)板屬性,如顏色,是否填充等。
paint.setStyle(Paint.Style.FILL);
canvas.drawArc(200,100,800,500,180,60,false,paint);
以上兩句代碼畫(huà)出的形狀是

5,畫(huà)筆的一些方法
1:用paint的時(shí)候有三種Style,分別是
Paint.Style.STROKE 只繪制圖形輪廓(描邊)
Paint.Style.FILL 只繪制圖形內(nèi)容 ,默認(rèn)是Paint.Style.FILL
Paint.Style.FILL_AND_STROKE 既繪制輪廓也繪制內(nèi)容
image.png
2:mPaint.setStrokeWidth(40);//用來(lái)設(shè)置畫(huà)筆的寬度
6,設(shè)置畫(huà)布的顏色,這類(lèi)顏色填充方法一般用于在繪制之前設(shè)置底色,或者在繪制之后為界面設(shè)置半透明蒙版。
canvas.drawColor(Color.RED);
canvas.drawARGB(100,100,100,100);
canvas.drawRGB(100,100,100);
7,設(shè)置線條的寬度,在STROKE和FILL_AND_STROKE下使用
paint.setStrokeWidth(10);//設(shè)置線條寬度為10像素
8,在繪制的時(shí)候,往往需要開(kāi)啟抗鋸齒來(lái)讓圖形和文字的邊緣更加平滑
paint=new Paint(Paint.ANTI_ALIAS_FLAG);//靜態(tài)開(kāi)啟抗鋸齒
paint.setAntiAlias(true);//動(dòng)態(tài)開(kāi)啟抗鋸齒
9,繪制一個(gè)點(diǎn),前兩個(gè)參數(shù)是x,y坐標(biāo),點(diǎn)的大小可以通過(guò)paint.setStrokeWidth來(lái)設(shè)置,點(diǎn)的形狀可以通過(guò)paint.setStrokeCap來(lái)設(shè)置,其中,SQUARE或BUTT畫(huà)出來(lái)是方形的點(diǎn),ROUND畫(huà)出來(lái)是圓形的點(diǎn)。
canvas.drawPoint(100,100,paint);
10,畫(huà)橢圓
canvas.drawOval(100,100,200,500,paint);
11,畫(huà)線,由于直線不是封閉圖形,所以paint.setStyle對(duì)直線沒(méi)有影響,canvas.drawLine是畫(huà)一條線,可以用canvas.drawLines批量畫(huà)線
canvas.drawLine(200,200,400,400,paint);
12,畫(huà)圓角矩形,第五個(gè)和第六個(gè)參數(shù)是矩形的每個(gè)圓角的橫向半徑和縱向半徑
canvas.drawRoundRect(200,300,400,500,80,80,paint);
13,根據(jù)path畫(huà)圖形
canvas.drawPath(path, paint);
其中,Path對(duì)象有如下
第一組,add...方法(添加完整封閉圖形,除了addPath())
path.addCircle(300,300,200, Path.Direction.CW);//添加圓
//path.addOval();//添加橢圓
//path.addRect();//添加矩形
//path.addRoundRect();添加圓角矩形
//path.addPath();添加path
第二組,...To方法(畫(huà)直線或者曲線)
//lineTo和rLineTo畫(huà)直線
paint.setStyle(Paint.Style.STROKE);//如果參數(shù)是Paint.Style.FILL,那么畫(huà)出來(lái)的是個(gè)三角形,和上面的那個(gè)畫(huà)圓弧的一樣,將畫(huà)筆style設(shè)置為FILL
path.lineTo(100,100);//參數(shù)是絕對(duì)坐標(biāo),由當(dāng)前位置(0,0)向(100,100)畫(huà)一條直線
path.rLineTo(100,0);//參數(shù)是相對(duì)坐標(biāo),由當(dāng)前位置(100,100)向正右方100像素的位置畫(huà)一條直線
canvas.drawPath(path, paint);
//moveTo移動(dòng)原點(diǎn)位置
paint.setStyle(Paint.Style.STROKE);
path.lineTo(100,100);//相對(duì)于原點(diǎn)(0,0)畫(huà)直線到點(diǎn)(100,100)
path.moveTo(200,100);//此時(shí)原點(diǎn)坐標(biāo)為(200,100)
path.lineTo(200,0);//相對(duì)于原點(diǎn)(200,100)畫(huà)直線到點(diǎn)(200,0),注意這個(gè)(200,0)點(diǎn)還是以(0,0)為原點(diǎn)的(200,0)點(diǎn),因?yàn)橛玫氖莑ineTo,如果是rLineTo()則原點(diǎn)為(200,100)
canvas.drawPath(path, paint);
//arcTo畫(huà)弧線
paint.setStyle(Paint.Style.STROKE);
path.lineTo(100,100);
path.arcTo(100,100,300,300,-90,90,false);//第七個(gè)參數(shù)為直線連線連到弧形起點(diǎn),true為無(wú)痕跡,false為有痕跡,如果沒(méi)有path.lineTo(100,100);這句
//代碼的話,true和false的效果是一樣的
canvas.drawPath(path, paint);
//addArc畫(huà)弧線
paint.setStyle(Paint.Style.STROKE);
path.lineTo(100,100);
path.addArc(100,100,300,300,-90,90);//path.addArc(100,100,300,300,-90,90)相當(dāng)于path.arcTo(100,100,300,300,-90,90,true),addArc()相當(dāng)于arcTo()的第七個(gè)參數(shù)為true的簡(jiǎn)化版
canvas.drawPath(path, paint);
第三,Path的close方法,不是所有的子圖形都需要使用path的close()來(lái)封閉的,當(dāng)paint的style是FILL或者是FILL_AND_STROKE時(shí),Path會(huì)自動(dòng)封閉子圖形,這就是上面畫(huà)弧和畫(huà)兩條線,如果設(shè)置為FILL,畫(huà)出來(lái)的是填充的弧和三角形的原因。
paint.setStyle(Paint.Style.FILL);
path.moveTo(100,100);
path.lineTo(200,100);
path.lineTo(150,150);
canvas.drawPath(path, paint);//這里只繪制了兩條邊,但由于style是FILL,所以繪制時(shí)會(huì)自動(dòng)封口
第四,Path的setFillType方法,對(duì)于添加子圖形類(lèi)方法(如path.addCircle(),path.addRect())的方向,由方法的dir參數(shù)來(lái)控制,而對(duì)于畫(huà)線類(lèi)的方法(如path.lineTo(),path.arcTo())的方向就是圖形的方向
paint.setStyle(Paint.Style.FILL);
path.addCircle(300,300,200, Path.Direction.CCW);//CW順時(shí)針,CCW逆時(shí)針
path.addCircle(300,300,100, Path.Direction.CW);
path.setFillType(Path.FillType.INVERSE_WINDING);//EVEN_ODD是如果是奇數(shù)就繪制,也就是說(shuō)如果兩個(gè)圖形有部分重合,那么重合的那部分就不繪制,繪制剩下的
//WINDING是按方向進(jìn)行相加的,順時(shí)針?lè)较?1,逆時(shí)針?lè)较?1,最后為0的那部分不繪制,繪制剩下的
//INVERSE_EVEN_ODD就是將EVEN_ODD反過(guò)來(lái)
//INVERSE_WINDING就是將WINDING反過(guò)來(lái)
canvas.drawPath(path,paint);
來(lái)個(gè)圖片,通俗易懂

14,畫(huà)Bitmap
Bitmap bitmap=BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher);
...
canvas.drawBitmap(bitmap,100,100,paint);
15,繪制文字
paint.setTextSize(100);//設(shè)置文字的大小
canvas.drawText("你好啊",200,200,paint);
以前記錄過(guò)的
Paint a=new Paint();
a.setColor(Color.RED);
//a.setAlpha(100);
//a.setStyle(Style.FILL_AND_STROKE);//設(shè)置畫(huà)筆的風(fēng)格
//a.setStrokeWidth(33);//設(shè)置空心線寬
a.setTextSize(34);//設(shè)置畫(huà)筆字體的大小
//a.setTypeface(Typeface.DEFAULT_BOLD);//設(shè)置字體樣式
//a.setTextScaleX(55);//設(shè)置比例因子,以一為標(biāo)準(zhǔn)
//a.setARGB(40, 45, 88, 66);//設(shè)置字體的顏色
//a.setUnderlineText(true);//設(shè)置下劃線
//a.setTextSkewX(3);//設(shè)置傾斜因子,以零為標(biāo)準(zhǔn)
canvas.drawColor(Color.GREEN);//設(shè)置背景顏色
//canvas.drawText("n好啊", 70, 90, a);
///canvas.drawCircle(33, 22, 44, a);
//canvas.drawLine(33, 44, 11, 22, a);
//canvas.drawPoint(44, 55, a);
//canvas.drawRoundRect(new RectF(55,277,488,499), 35, 22, a);//繪制圓角矩形
//canvas.drawOval(new RectF(33,333,222,444), a);//繪制橢圓形
//Path ab=new Path();
//ab.moveTo(33, 44);
//ab.lineTo(77, 88);
//ab.lineTo(76, 55);
//canvas.drawPath(ab, a);//繪制任意多邊形
//canvas.drawArc(new RectF(33,44,333,444), 66, 55, true, a);//繪制圓弧
//Bitmap ac=((BitmapDrawable)getResources().getDrawable(R.drawable.ic_launcher)).getBitmap();
//canvas.drawBitmap(ac, 444, 44, a);//繪制圖像
//canvas.clipRect(44, 66, 222, 330);//裁剪指定的區(qū)域
//canvas.drawColor(Color.BLUE);
//canvas.drawText("旋轉(zhuǎn)字", 43, 333, a);
//canvas.save();
//canvas.rotate(60,43,333);
//canvas.drawText("旋轉(zhuǎn)字", 43, 333, a);
//canvas.restore();//關(guān)于畫(huà)布鎖定和解鎖,旋轉(zhuǎn)的例子
-----------------------------------------------------------------------------------
android群英傳中對(duì)canvas的介紹
1:Canvas.save(),Canvas.restore(),Canvas.translate(),Canvas.rotate()這四個(gè)方法的介紹如下:
Canvas.save()這個(gè)方法,從字面上可以理解為保存畫(huà)布,它的作用就是將之前的所有已繪制圖像保存起來(lái),讓后續(xù)的操作就好像在一個(gè)新的圖層上操作一樣,這一點(diǎn)點(diǎn)與photoshop中的圖層理解基本一致。
Canvas.restore()這個(gè)方法,則可以理解為photoshop中的合并圖層操作,它的作用是將我們?cè)趕ave()之后繪制的所有圖像與save()之前的圖像進(jìn)行合并。
translate()和rotate()方法,就是在調(diào)用translate(x,y)方法之后,將原點(diǎn)(0,0)移動(dòng)到(x,y)。之后的所有繪圖操作都將以(x,y)為原點(diǎn)執(zhí)行。同理totate()方法也是一樣的,它將坐標(biāo)系旋轉(zhuǎn)了一定的角度。
2:Layer圖層
在android中通過(guò)調(diào)用saveLayer()方法,saveLayerAlpha()方法創(chuàng)建一個(gè)圖層,使用restore()方法,restoreToCount()方法合并所有圖層。創(chuàng)建圖層的時(shí)候,后面所有的操作都發(fā)生在這個(gè)圖層上。saveLayerAlpha()的第五個(gè)參數(shù)的取值如果是0比表示完全透明,127表示半透明,255表示完全不透明。示例代碼如下:
canvas.drawCircle(300,300,200,paint);
canvas.saveLayerAlpha(0,0,600,600,127);
paint.setColor(Color.GREEN);
canvas.drawCircle(300,300,300,paint);
canvas.restore();
圖如下所示:

3:PorterDuffXfermode(參考文章:http://www.itdecent.cn/p/0f64daf202f2)

示例代碼如下:
...
canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),paint);//必須要新建一個(gè)圖層才能看到混合后的效果了
canvas.drawCircle(0,0,bitmap.getWidth()/2,paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap,0,0,paint);
paint.setXfermode(null);// 還原混合模式
canvas.restore();//合并圖層
...
效果如下:

4:Shader,著色器,渲染器,Shader包括:BitmapShader(位圖Shader),LinearGradient(線性Shader),RadialGradient(光速Shader),SweepGradient(梯度Shader),ComposeShader(混合Shader)
4.1:BitmapShader的使用,填充模式有三種CLAMP(拉伸),REPEAT(重復(fù)),MIRROR(鏡像),示例代碼如下:
paint.setShader(new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
canvas.drawCircle(canvas.getWidth() / 2, canvas.getHeight() / 2, canvas.getWidth() / 2 > canvas.getHeight() / 2 ? canvas.getHeight() / 2 : canvas.getWidth() / 2, paint);
結(jié)果如下所示:

4.2:LinearGradient的使用,示例代碼如下:
paint.setShader(new LinearGradient(0,0,canvas.getWidth(),canvas.getHeight(),Color.BLUE,Color.GREEN, Shader.TileMode.CLAMP));
canvas.drawCircle(canvas.getWidth() / 2, canvas.getHeight() / 2, canvas.getWidth() / 2 > canvas.getHeight() / 2 ? canvas.getHeight() / 2 : canvas.getWidth() / 2, paint);
結(jié)果如下所示:

小技巧:Marix.setScale(1F,-1F)可以實(shí)現(xiàn)圖片的垂直翻轉(zhuǎn)。
5:PathEffect
5.1:DiscretePathEffect,使用這個(gè)效果之后,線段上就會(huì)產(chǎn)生許多雜點(diǎn)
paint.setPathEffect(new DiscretePathEffect(3f,5f));
Path path=new Path();
path.moveTo(0,canvas.getHeight()/2);
path.lineTo(canvas.getWidth()/3,0);
path.lineTo(canvas.getWidth()/3*2,canvas.getHeight());
path.lineTo(canvas.getWidth(),0);
canvas.drawPath(path,paint);
效果圖如下:

5.2:DashPathEffect,這個(gè)效果可以用來(lái)繪制虛線,用一個(gè)數(shù)組來(lái)設(shè)置各個(gè)點(diǎn)之間的間隔,此后繪制虛線時(shí)就重復(fù)這樣的間隔進(jìn)行繪制,另一個(gè)參數(shù)則用來(lái)控制繪制時(shí)數(shù)組的一個(gè)偏移量,通??梢酝ㄟ^(guò)設(shè)置值來(lái)實(shí)現(xiàn)路徑的動(dòng)態(tài)效果。
paint.setPathEffect(new DashPathEffect(new float[]{20,10,5,10},0));
效果圖如下:

5.3:PathDashPathEffect,這個(gè)效果和DashPathEffect效果類(lèi)似,只不過(guò)它的功能更加強(qiáng)大,可以設(shè)置顯示點(diǎn)的圖形,即方形點(diǎn)的虛線,圓形點(diǎn)的虛線。
Path path1=new Path();
path1.addRect(0,0,8,8,Path.Direction.CCW);
paint.setPathEffect(new PathDashPathEffect(path1,12f,0,PathDashPathEffect.Style.ROTATE));
效果圖如下:

5.4:CornerPathEffect,就是將拐角處變得圓滑,具體圓滑的程度,則由參數(shù)決定。
paint.setPathEffect(new CornerPathEffect(30));
效果圖如下:

5.5:ComposePathEffect,將任意兩種路徑特效組合起來(lái)形成一個(gè)新的效果。
PathEffect pathEffect=new CornerPathEffect(30);
PathEffect pathEffect1=new DashPathEffect(new float[]{20,10,5,10},0);
paint.setPathEffect(new ComposePathEffect(pathEffect,pathEffect1));
效果圖如下:

5.6:SumPathEffect,將任意兩種路徑特效組合起來(lái)形成一個(gè)新的效果。
PathEffect pathEffect=new CornerPathEffect(30);
PathEffect pathEffect1=new DashPathEffect(new float[]{20,10,5,10},0);
paint.setPathEffect(new SumPathEffect(pathEffect,pathEffect1));
效果圖如下:

