上篇的學(xué)習(xí),Paint
中的基礎(chǔ)知識基本結(jié)束,筆學(xué)完了,學(xué)習(xí)開始學(xué)習(xí)畫布。本篇記錄學(xué)習(xí)Canvas
中的一些知識。在drawBitmap()
方法中會引出計(jì)劃下篇要學(xué)習(xí)的內(nèi)容Matrix
,drawPath()
方法會引出計(jì)劃在下下篇學(xué)習(xí)的貝塞爾曲線,學(xué)習(xí)的重點(diǎn)也是這兩個(gè)方法
學(xué)習(xí)資料:
本人很菜,有錯(cuò)誤,請指出
雖然稱Canvas
為畫布,但并不是直接在Canvas
畫,Canvas
內(nèi)部默認(rèn)會創(chuàng)建一個(gè)Biatmap
,也可以通過構(gòu)造方法或者setBitmap()
方法傳入一個(gè),像素所有的信息是畫在了這個(gè)Bitmap
上,然后Bitmap
被保存在了Canvas
之內(nèi)
這是我看愛哥的博客后,自己做的一個(gè)總結(jié),若有錯(cuò)誤,請指出。針對
Canvas
的兩種構(gòu)造方法,愛哥針對源碼有做分析,可以看看了解一下
在Canvas
的方法中,clip
和draw
方法占據(jù)了一大半,在Android 自定義View學(xué)習(xí)(二)——開始了解Canvas和Paint了解過了幾個(gè)draw
方法,本篇進(jìn)行補(bǔ)充學(xué)習(xí)
1.draw方法補(bǔ)充學(xué)習(xí)
在draw
一系列方法中,有一個(gè)特殊的牛B的存在,drawBitmapMesh()
,這個(gè)方法牛B在可以幾乎對Bitmap
做任何操作。雖然這個(gè)方法很強(qiáng)大,但使用的頻率并不算高,也有點(diǎn)雞肋。一些比較簡單的Bitmap
處理可能優(yōu)先考慮Matrix
,而過于復(fù)雜的處理,會耗時(shí)比較久,效率可能并不高。一般優(yōu)先不考慮這個(gè)方法,遇到Matrix
實(shí)現(xiàn)不了的需求,記得有這么一個(gè)方法可以學(xué)習(xí),然后使用
1.1 drawBitmap方法
感覺這個(gè)方法使用頻率很高。一共有6個(gè)重載方法,其中兩個(gè)參數(shù)最多的方法已經(jīng)廢棄,也就是需要學(xué)習(xí)4個(gè)
1.1.1 第1個(gè)方法
drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint)
-
bitmap
要畫的目標(biāo)Bitmap
-
left
左上角的X
軸坐標(biāo) -
top
左上角的Y
軸坐標(biāo) -
paint
畫筆
簡單使用
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
final Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test);
final float x = getWidth() / 2 - bitmap.getWidth() / 2;//水平居中
final float y = 0;
canvas.drawBitmap(bitmap, x, y, mPaint);
}
在實(shí)際開發(fā)中,還會考慮圖片寬高的壓縮,顯示位置,以及padding
的等等
1.1.2 第2個(gè)和第3個(gè)方法
drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull Rect dst,@Nullable Paint paint)
drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull RectF dst,@Nullable Paint paint)
兩個(gè)方法的差別在于第三個(gè)參數(shù)Rect
和RectF
-
src
用來截取Bitmap
局部所想要顯示的像素塊區(qū)域,通過構(gòu)造方法中的四個(gè)坐標(biāo)系點(diǎn)確定范圍。這個(gè)參數(shù)可以為null
,為null
就是整個(gè)Bitmap
都作為目標(biāo)資源顯示 -
dst
用來顯示的區(qū)域,在控件中繪制Bitmap
的區(qū)域,可以實(shí)現(xiàn)拉伸或者縮放
簡單使用
private void init() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.test);
rect = new Rect(0,0,1080,600);
rectF = new RectF(0f,0f,1080f,600f);
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (bitmap != null)
canvas.drawBitmap(bitmap,null,rectF,mPaint);
}
1080
是測試手機(jī)的屏幕寬度
第2個(gè)參數(shù)rect = new Rect(x,y,x1,y1)
,構(gòu)造方法中四個(gè)參數(shù)分別為:
-
x
, X軸開始的坐標(biāo)點(diǎn),默認(rèn)為0 -
y
, Y軸開始的坐標(biāo)點(diǎn) -
x1
, X軸結(jié)束的坐標(biāo)點(diǎn),若x1-x
大于了Bitmap
的寬度,截取的有效區(qū)域就是Bitmap
的寬度 -
y1
, Y軸結(jié)束的坐標(biāo)點(diǎn)
第3個(gè)參數(shù)rectF = new RectF(x,y,x1,y1)
,構(gòu)造方法中四個(gè)參數(shù)分別為:
-
x
,開始繪制的X軸的坐標(biāo)點(diǎn),默認(rèn)為0 -
y
,開始繪制的Y軸的坐標(biāo)點(diǎn) -
x1
,結(jié)束繪制的X軸的坐標(biāo)點(diǎn),若x1-x
大于src
中x1-x
,就是拉伸;小于就是縮放 -
y1
,結(jié)束繪制的Y軸的坐標(biāo)點(diǎn)
簡單修改代碼:
rect = new Rect(0,0,400,600);
rectF = new RectF(100f,0f,700f,600f);
此時(shí)在控件X
軸100f
位置開始繪制資源Bitmap
的(0,0)到(400,600)
局部區(qū)域,最終的顯示效果就成了拉伸局部的效果。Y
軸同理
這兩個(gè)參數(shù)的作用,用幾個(gè)數(shù)簡單測試一下,比較直觀。
1.1.3 第4個(gè)方法
drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint)
簡單使用
private void init() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test);
matrix = new Matrix();
matrix.setTranslate(100f,100f);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(bitmap,matrix,mPaint);
}
Matrix
是一個(gè)3 * 3
的矩陣,下篇進(jìn)行記錄學(xué)習(xí)
1.2 畫Line方法
畫一條線的方法
drawLine(float startX, float startY, float stopX, float stopY, @NonNull Paint paint)
畫多條線的方法
drawLines(@Size(multiple=4) @NonNull float[] pts, @NonNull Paint paint)
drawLines(@Size(multiple=4) @NonNull float[] pts, int offset, int count,@NonNull Paint paint)
1.2.1 drawLine 畫一條線
drawLine()
方法就一個(gè),沒有重載方法。畫規(guī)則曲線可以考慮使用Path
private void init() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.parseColor("#FF4081"));
mPaint.setStrokeWidth(10f);
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawLine(100f,100f,600f,500f,mPaint);
}
方法參數(shù)也很簡單,四個(gè)參數(shù)確定兩個(gè)點(diǎn)的坐標(biāo),然后兩點(diǎn)一線
1.2.2 drawLines畫多條直線
兩個(gè)參數(shù)的drawsLines(float[] pts, Paint paint)
方法簡單使用
private void init() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.parseColor("#FF4081"));
mPaint.setStrokeWidth(10f);
floats = new float[]{100f,100f,300f,300f,400f,200f,600f,200f};//每4個(gè)數(shù)一組,確定兩個(gè)點(diǎn)的坐標(biāo)
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawLines(floats,mPaint);
}
方法源碼中有這樣一個(gè)@Size(multiple=4)
注解,要求floats
中每4個(gè)值看做一組,每組來確定一條直線的兩個(gè)端點(diǎn),不足4個(gè)的部分是無效的
兩個(gè)參數(shù)的方法內(nèi)部還是調(diào)用了四個(gè)參數(shù)的方法,在源碼中
public void drawLines(@Size(multiple=4) @NonNull float[] pts, @NonNull Paint paint) {
drawLines(pts, 0, pts.length, paint);
}
在drawLines(float[] pts, int offset, int count,Paint paint)
中,
-
offset
表示跳過floats
中幾個(gè)值 -
count
表示跳過offset
后,數(shù)組的長度
簡單修改代碼
canvas.drawLines(floats,4,floats.length-4,mPaint);
就只會畫出(400f,200f),(600f,200f)
確定的那條水平的短線
1.3 畫Potion方法
同1.2畫Line
方法一樣,畫點(diǎn)的方法也是有兩種,畫一個(gè)點(diǎn)和畫多個(gè)點(diǎn)
畫一個(gè)點(diǎn)很簡單,直接看畫多個(gè)點(diǎn)
drawPoints(@Size(multiple=2) float[] pts, int offset, int count,@NonNull Paint paint)
根據(jù)方法內(nèi)的注解得知,pts
的大小要大于2,并且每兩個(gè)一組,多余的無效
簡單使用:
private void init() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.parseColor("#FF4081"));
mPaint.setStrokeWidth(10f);
floats = new float[]{100f,100f,300f,200f,200f};
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPoints(floats,mPaint);
}
在floats
中,有5個(gè)值,但實(shí)際有效的也就是前4個(gè)
1.3 drawPath 方法
在Android 自定義View學(xué)習(xí)(三)——Paint繪制文字屬性中學(xué)習(xí)了解了setPathEffect(PathEffect effect)
方法在繪制路徑時(shí)的效果,drawPath()
方法往往都會配合PahtEffect
來使用
drawPath(@NonNull Path path, @NonNull Paint paint)
方法只有一個(gè),簡單使用
private void init() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.parseColor("#FF4081"));
mPaint.setStyle(Paint.Style.STROKE);//設(shè)置風(fēng)格為空心
mPaint.setStrokeWidth(10f);
path = new Path();
path.moveTo(540f,50f);
path.lineTo(740f,300f);
path.lineTo(340f,300f);
path.close();//形成閉合 將(340,300)和(540,50)連接起來
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(path, mPaint);
}
繪制出一個(gè)等腰三角形
主要就是用到Path
這個(gè)類,這個(gè)類有很多方法除了可以繪制直線,還可以繪制曲線
1.3.1 Path類
The Path class encapsulates compound (multiple contour) geometric paths consisting of straight line segments, quadratic curves, and cubic curves.
It can be drawn with canvas.drawPath(path, paint), either filled or stroked (based on the paint's Style), or it can be used for clipping or to draw text on a path.
這個(gè)類封裝了一些可以借助一元直線方程,二遠(yuǎn)方程曲線,立方曲線的方法來繪制一些較為復(fù)雜的組合形式的集合圖形,繪制出來的風(fēng)格則是根據(jù)畫筆設(shè)置的style
來決定,也可以剪切或者繪制一段文字在路徑上
除了已經(jīng)用到的moveTo()
和lineTo()
方法,Path
中還有很多add
開頭的方法。有兩個(gè)重點(diǎn)方法是quadTo()
和cubicTo()
方法
1.3.1 quadTo和cubicTo方法
quadTo()
可以用來繪制二階貝塞爾曲線,也就是3個(gè)點(diǎn)確定一個(gè)曲線
private void init() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.parseColor("#FF4081"));
mPaint.setStyle(Paint.Style.STROKE);//設(shè)置風(fēng)格為空心
mPaint.setStrokeWidth(10f);
path = new Path();
path.moveTo(100f,100f);
floats = new float[]{200f,200f,900f,100f};
path.quadTo(200f,200f,900f,100f);
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(path, mPaint);
canvas.drawPoints(floats,mPaint);
}
圖中的曲線,是由(100,100),(900,100),(200,200)
三個(gè)點(diǎn)來確定。
cubicTo
方法使用和quadTo
用法類似,只是多了一組參數(shù),多了一個(gè)點(diǎn)而已
path.cubicTo(200f,200f,400f,100f,900f,200f);
測試效果和quadTo
很容易就分區(qū)
依稀記得高三的數(shù)學(xué)考試最后一道大題往往就是要求繪制會一個(gè)點(diǎn)的運(yùn)動軌跡,大部分都是一段曲線或者一個(gè)橢圓之類的,和這里有些類似。
這兩方法重要的是理解其中的原理,貝爾塞爾曲線等到Matrix
學(xué)習(xí)結(jié)束后再進(jìn)行學(xué)習(xí)
1.3.2 addTo方法
先來看簡單用法
private void init() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.parseColor("#FF4081"));
mPaint.setStyle(Paint.Style.STROKE);//設(shè)置風(fēng)格為空心
mPaint.setStrokeWidth(10f);
path = new Path();
path.moveTo(100f,100f);
rectF = new RectF(100, 100, 400, 400);
path.arcTo(rectF,0,90);
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(path, mPaint);
}
這個(gè)方法就是畫出一段弧線后,將弧線的起始點(diǎn)和moveTo
確定的path
的起始點(diǎn)進(jìn)行連接起來?;【€截取圓的一部分。圓的直徑為300,經(jīng)過很簡單分析,圓心在(250,250)
的點(diǎn)
1.3.3 rLineTo方法
r
就是relative
,相對的縮寫
簡單使用
private void init() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.parseColor("#FF4081"));
mPaint.setStyle(Paint.Style.STROKE);//設(shè)置風(fēng)格為空心
mPaint.setStrokeWidth(10f);
path = new Path();
path.moveTo(100f,100f);
path.rLineTo(300,200f);
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(path, mPaint);
canvas.drawPoint(300,200,mPaint);
}
rLineTo
方法確定的坐標(biāo)是相對于moveTo
來說的,實(shí)際最終的畫出的直線的結(jié)束點(diǎn)的坐標(biāo)為(400,300)
1.3.4 addArc方法
簡單使用
private void init() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.parseColor("#FF4081"));
mPaint.setStyle(Paint.Style.STROKE);//設(shè)置風(fēng)格為空心
mPaint.setStrokeWidth(10f);
path = new Path();
path.moveTo(100f,100f);
path.lineTo(300,200f);
//添加弧形
rectF = new RectF(100, 100, 400, 400);
path.addArc(rectF,0,90);
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(path, mPaint);
canvas.drawPoint(300,200,mPaint);
}
addArc
方法和addTo
方法卻別是,addArc
是添加一段弧形,并不將繪制的圖形連接起來
1.4 canvas.drawTextOnPath 方法
在繪制的路徑上,繪制文字
private void init() {
//路徑畫筆
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.parseColor("#FF4081"));
mPaint.setStyle(Paint.Style.STROKE);//設(shè)置風(fēng)格為空心
mPaint.setStrokeWidth(10f);
//文字畫筆
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setTextSize(60f);
//路徑
path = new Path();
rectF = new RectF(100, 100, 300, 400);
path.addOval(rectF, Path.Direction.CW);
chars = new char[]{'a','b','c','d','e'};
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//繪制路徑
canvas.drawPath(path, mPaint);
//繪制路徑上的文字
canvas.drawTextOnPath(chars,0,chars.length,path,0f,chars.length,textPaint);
}
在addOval
方法中,可以改變路徑閉合的方向,簡單修改代碼
path.addOval(rectF, Path.Direction.CCW);
文字在路徑內(nèi)側(cè)繪制,并且逆時(shí)針
draw
系列方法中,有一個(gè)看起來很有意思的方法,drawTextRun
方法,但這個(gè)方法最低要求的23
canvas.drawTextRun(chars,0,chars.length,0,chars.length,100f,100f,false,textPaint);
沒有23的真機(jī),就用了虛擬機(jī),看方法名字,以為會按照一定的方法,文字進(jìn)行滾動,可并沒有,設(shè)置為false
為abcde
,設(shè)置為true
為edcba
,不清楚在真機(jī)上啥效果
加上在開始了解Canvas
中的方法,draw
大致就學(xué)習(xí)到這里
2.Clip方法學(xué)習(xí)
Clip
開頭的方法主要有兩個(gè):
-
clipPath()
利用Path
的方法,可以裁切出一塊不規(guī)則區(qū)域畫布 -
clipRect()
可以裁切出一塊矩形畫布
還有一個(gè)已經(jīng)廢棄的clipRegion()
,廢棄就不學(xué)了,直接學(xué)替代的方法
2.1 clipRect裁切規(guī)則區(qū)域畫布
簡單使用:
private void init() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.parseColor("#FF4081"));
mPaint.setStyle(Paint.Style.FILL);
//矩形
rectF = new RectF(0, 0, 400, 400);
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//繪制底色 黃
canvas.drawColor(Color.YELLOW);
//截取畫布
canvas.clipRect(rectF);
//截取后的畫布底色
canvas.drawColor(Color.CYAN);
//驗(yàn)證有效區(qū)域
canvas.drawRect(300,300,600,600,mPaint);
}
clipRect(rectF)
,就是在在畫布裁出以(0,0),(0,400),(400,0),(400,400)
四個(gè)點(diǎn)確定的矩形。之后Canvas
有效的區(qū)域便就是裁出的矩形區(qū)域,再次進(jìn)行繪制時(shí),超出這個(gè)區(qū)域便無法繪制,但裁切并不會影響c裁切前已經(jīng)繪制好的區(qū)域,clip
裁切針對的是Canvas
cliprRect
有這樣一個(gè)cliprRect((@NonNull RectF rect, @NonNull Region.Op op)
重載方法
2.1.1 Region.Op
Op
是Region
類中的一個(gè)枚舉,有6個(gè)值
直接用代碼演示效果
private void init() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.WHITE);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(5f);
//裁切區(qū)域1
rectF1 = new RectF(100, 100, 300, 300);
//裁切區(qū)域2
rectF2 = new RectF(200, 200, 400, 400);
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//繪制底色 藍(lán)
canvas.drawColor(Color.BLUE);
canvas.save();
//截取畫布1
canvas.clipRect(rectF1);
//截取畫布2
canvas.clipRect(rectF2,Region.Op.DIFFERENCE);
//截取后的有效區(qū)域畫布底色
canvas.drawColor(Color.RED);
canvas.restore();
//繪制輔助區(qū)域
canvas.drawRect(rectF1, mPaint);
canvas.drawRect(rectF2, mPaint);
}
紅色區(qū)域就代表兩次裁切后的有效區(qū)域
- Region.Op.DIFFERENCE
取第一次裁切的非交集部分
- Region.Op.INTERSECT
取兩次的交集
- Region.Op.REPLACE
第二次替代第一次裁切
- Region.Op.UNION
兩次裁切的和
- Region.Op.REVERSE_DIFFERENCE
與DIFFERENCE
相反,取的第2次裁切的非交集區(qū)域
- Region.Op.XOR
異或,取兩次交集外的區(qū)域
有點(diǎn)類似PorterDuffXfermode
圖像處理的效果
2.2 CilpPath 裁切不規(guī)則畫布
裁切出一個(gè)圓形區(qū)域的畫布
private void init() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.WHITE);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(5f);
path = new Path();
path.addCircle(300,300,100, Path.Direction.CCW);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//繪制底色 藍(lán)
canvas.drawColor(Color.BLUE);
//裁切畫布
canvas.clipPath(path);
//繪制裁切后的區(qū)域底色
canvas.drawColor(Color.parseColor("#FF4081"));
//繪制輔助圓形
canvas.drawCircle(300,300,100,mPaint);
}
clip
的方法基本就學(xué)到這里
3.其他方法
畫布除了裁切外,還有可以進(jìn)行旋轉(zhuǎn)
3.1 rotate 旋轉(zhuǎn)方法
private void init() {
rectP1 = new Paint(Paint.ANTI_ALIAS_FLAG);
rectP1.setColor(Color.BLUE);
rectP2 = new Paint(Paint.ANTI_ALIAS_FLAG);
rectP2.setColor(Color.parseColor("#FF4081"));
rectF1 = new RectF(100,100,400,400);
rectF2 = new RectF(200,200,300,300);
}
/**
* 旋轉(zhuǎn)畫布
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//旋轉(zhuǎn)30°
canvas.rotate(30);
canvas.drawRect(rectF1,rectP1);
canvas.drawRect(rectF2,rectP2);
}
整個(gè)畫布進(jìn)行了順時(shí)針旋轉(zhuǎn)30°
,參數(shù)為正時(shí),是順時(shí)針旋轉(zhuǎn),負(fù)數(shù)為逆時(shí)針旋轉(zhuǎn)
如果只想讓小的紅色的矩形進(jìn)行旋轉(zhuǎn),而藍(lán)色的大矩形不旋轉(zhuǎn),需要了解畫布中的層
3.2 save和restore方法
簡單修改代碼,加入save
和restore
兩個(gè)方法
private void init() {
rectP1 = new Paint(Paint.ANTI_ALIAS_FLAG);
rectP1.setColor(Color.BLUE);
rectP2 = new Paint(Paint.ANTI_ALIAS_FLAG);
rectP2.setColor(Color.parseColor("#FF4081"));
rectF1 = new RectF(100,100,400,400);
rectF2 = new RectF(200,200,300,300);
}
/**
* 旋轉(zhuǎn)畫布
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRect(rectF1,rectP1);
canvas.save();
//旋轉(zhuǎn)30°
canvas.rotate(30);
canvas.drawRect(rectF2,rectP2);
canvas.restore();
}
save()
就是保存當(dāng)前圖層
restore()
就是把圖層恢復(fù)到最近一次save()
方法前的狀態(tài)
關(guān)于保存圖層,還有一個(gè)更加強(qiáng)大的saveLayer()
,這個(gè)方法就等用到時(shí),再進(jìn)行學(xué)習(xí)
3.3 translate 平移畫布
這個(gè)方法使用很簡單
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//平移
canvas.translate(800,200);
//繪制矩形
canvas.drawRect(rectF1,rectP1);
canvas.drawRect(rectF2,rectP2);
//在(100,100)處繪制一個(gè)小圓,用來輔助觀察坐標(biāo)系的改變
canvas.drawCircle(100,100,30,rectP2);
}
這個(gè)方法需要注意的是,Canvas
的坐標(biāo)系就進(jìn)行了改變,觀察小圓的位置
3.4 scale 縮放方法
縮放的使用也非常簡單
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.scale(0.5F, 1.0F);
canvas.drawBitmap(bitmap,0,0,null);
}
縮放有效值為0~1f
,1表示不進(jìn)行縮放,原始大小
縮放方法有個(gè)重載方法scale(float sx, float sy, float px, float py)
簡單修改代碼
canvas.scale(0.5F, 1.0F,540,0);
px,py
確定縮放中心,canvas.scale(0.5F, 1.0F)
默認(rèn)為(0,0)
為縮放中心,指定(540,0)
為縮放中心時(shí),屏幕寬度為1080
,Canvas
就在水平居中縮放
3.5 skew 錯(cuò)切
簡單使用
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.skew(0.5f,0);
canvas.drawBitmap(bitmap,0,0,null);
}
這幾個(gè)方法都只是簡單的調(diào)用,看了看效果,以后用到就再深入了解學(xué)習(xí)
4. 最后
Canvas
的基本知識也就學(xué)習(xí)這些,遺漏的遇到再學(xué)習(xí)
篇幅有點(diǎn)長,但并不難理解,基本都是調(diào)用一下就可以比較直觀看出效果的方法
下篇學(xué)習(xí)Matrix
月餅節(jié)到了,中秋快樂 : )