自定義控件教程:
1,http://blog.csdn.net/aigestudio/article/details/41212583
2,http://blog.csdn.net/aigestudio/article/details/41316141
3,http://blog.csdn.net/aigestudio/article/details/41447349
4,http://blog.csdn.net/aigestudio/article/details/41960507
5,http://blog.csdn.net/aigestudio/article/details/42677973
6,http://blog.csdn.net/aigestudio/article/details/42989325
1,Paint類
private void init() {
paint = new Paint();
paint.setAntiAlias(true);//反鋸齒
paint.setColor(Color.RED);
/*
* 設(shè)置畫(huà)筆樣式為描邊,圓環(huán)嘛……當(dāng)然不能填充不然就么意思了
*
* 畫(huà)筆樣式分三種:
* 1.Paint.Style.STROKE:描邊
* 2.Paint.Style.FILL_AND_STROKE:描邊并填充
* 3.Paint.Style.FILL:填充
*/
paint.setStyle(Paint.Style.FILL);
/*
* 設(shè)置描邊的粗細(xì),單位:像素px
* 注意:當(dāng)setStrokeWidth(0)的時(shí)候描邊寬度并不為0而是只占一個(gè)像素
*/
paint.setStrokeWidth(paintStrokeWidth);
}
Paint的其他方法:
setStrokeCap(Paint.Cap cap)
方法,該方法用來(lái)設(shè)置我們畫(huà)筆的筆觸風(fēng)格,上面的例子中我使用的是ROUND,表示是圓角的筆觸,那么什么叫筆觸呢,其實(shí)很簡(jiǎn)單,就像我們現(xiàn)實(shí)世界中的筆,如果你用圓珠筆在紙上戳一點(diǎn),那么這個(gè)點(diǎn)一定是個(gè)圓,即便很小,它代表了筆的筆觸形狀,如果我們把一支鉛筆筆尖削成方形的,那么畫(huà)出來(lái)的線條會(huì)是一條彎曲的“矩形”,這就是筆觸的意思。除了ROUND,Paint.Cap還提供了另外兩種類型:SQUARE和BUTTsetStrokeJoin(Paint.Join join)
這個(gè)方法用于設(shè)置結(jié)合處的形態(tài),就像上面的代碼中我們雖說(shuō)是花了一條心電線,但是這條線其實(shí)是由無(wú)數(shù)條小線拼接成的,拼接處的形狀就由該方法指定。setShadowLayer(float radius, float dx, float dy, int shadowColor)
該方法為我們繪制的圖形添加一個(gè)陰影層效果:
TextPaint專門用戶繪制文字的畫(huà)筆
/*
* 初始化文字畫(huà)筆
*/
textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG | Paint.SUBPIXEL_TEXT_FLAG);
textPaint.setColor(Color.WHITE);
textPaint.setTextSize(30);
textPaint.setTextAlign(Paint.Align.CENTER);
與畫(huà)筆顏色相關(guān)的類
詳情見(jiàn)博客:2,http://blog.csdn.net/aigestudio/article/details/41316141
PorterDuffXfermode類,圖形混合模式的意思
2,View類的invalidate()方法,和postInvalidate()方法
在Android中提供了一個(gè)叫invalidate()的方法來(lái)讓我們重繪我們的View。poistInvalidate()方法和invaliadate方法相同,只是它可以在子線程中運(yùn)行.
nvalidate()方法只能在主線程中調(diào)用,而postInvalidate()方法可以在子線程中調(diào)用。
3,Shader類(著色器)
Shader類呢也是個(gè)灰常灰常簡(jiǎn)單的類,它有五個(gè)子類,像PathEffect一樣每個(gè)子類都實(shí)現(xiàn)了一種Shader,Shader在三維軟件中我們稱之為著色器,其作用嘛就像它的名字一樣是來(lái)給圖像著色的或者更通俗的說(shuō)法是上色!這么說(shuō)該懂了吧!再不懂去廁所哭去!這五個(gè)Shader里最異類的是BitmapShader,因?yàn)橹挥兴窃试S我們載入一張圖片來(lái)給圖像著色,那我們還是先來(lái)看看這個(gè)怪胎吧BitmapShader只有一個(gè)含參的構(gòu)造方法BitmapShader (Bitmap bitmap, Shader.TileMode tileX, Shader.TileMode tileY)
BitmapShader (Bitmap bitmap, Shader.TileMode tileX, Shader.TileMode tileY)的第一個(gè)參數(shù)是位圖這個(gè)很顯然,而后兩個(gè)參數(shù)則分別表示XY方向上的著色模式。
Shader.TileMode里有三種模式:CLAMP、MIRROR和REPETA。MIRROR鏡像效果,REPETA重復(fù),CLAMP的意思就是邊緣拉伸的意思
4,Canvas 畫(huà)布
- canvas.save();鎖定畫(huà)布
- canvas.restore(); 釋放畫(huà)布,即將畫(huà)布釋放到之前鎖定的位置。先調(diào)用sava()方法,才能調(diào)用restore()方法進(jìn)行釋放。
在Android中我們可以使用Canvas的saveXXX和restoreXXX方法來(lái)模擬圖層的類似效果
Canvas我們一直稱其為畫(huà)布,其實(shí)更準(zhǔn)確地說(shuō)Canvas是一個(gè)容器,如果把Canvas理解成畫(huà)板,那么我們的“層”就像張張夾在畫(huà)板上的透明的紙,而這些紙對(duì)應(yīng)到Android則是一個(gè)個(gè)封裝在Canvas中的Bitmap。
除了save()方法Canvas還給我們提供了一系列的saveLayerXXX方法給我們保存畫(huà)布,與save()方法不同的是,saveLayerXXX方法會(huì)將所有的操作存到一個(gè)新的Bitmap中而不影響當(dāng)前Canvas的Bitmap,而save()方法則是在當(dāng)前的Bitmap中進(jìn)行操作,并且只能針對(duì)Bitmap的形變和裁剪進(jìn)行操作,saveLayerXXX方法則無(wú)所不能,當(dāng)然兩者還有很多的不同.
save和saveLayerXXX方法有著本質(zhì)的區(qū)別,saveLayerXXX方法會(huì)將所有操作在一個(gè)新的Bitmap中進(jìn)行,而save則是依靠stack棧來(lái)進(jìn)行
詳情:http://blog.csdn.net/aigestudio/article/details/42677973
- canvas.translate(x, y);平移畫(huà)布,就相當(dāng)于將畫(huà)布的原點(diǎn)移到x,y的位置 ,即相當(dāng)于坐標(biāo)系移動(dòng)了。
- canvas.rotate(degrees);旋轉(zhuǎn)畫(huà)布,將畫(huà)布按照一定角度進(jìn)行旋轉(zhuǎn),即相當(dāng)于坐標(biāo)系進(jìn)行了旋轉(zhuǎn)。
注意:畫(huà)布的平移旋轉(zhuǎn)同樣也會(huì)影響畫(huà)布的自身坐標(biāo)
5,Canvas類(畫(huà)布)
Canvas所提供的各種方法根據(jù)功能來(lái)看大致可以分為幾類,第一是以drawXXX為主的繪制方法,第二是以clipXXX為主的裁剪方法,第三是以scale、skew、translate和rotate組成的Canvas變換方法,最后一類則是以saveXXX和restoreXXX構(gòu)成的畫(huà)布鎖定和還原。
- drawBitmapMesh (Bitmap bitmap, int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors, int colorOffset, Paint paint)
很吊毛的方法,但是計(jì)算復(fù)雜度很高,所有被沉默了。(一般不推薦使用,因?yàn)橛?jì)算難度很大)
詳細(xì)原理http://blog.csdn.net/aigestudio/article/details/41960507
drawBitmapMesh是個(gè)很屌毛的方法,為什么這樣說(shuō)呢?因?yàn)樗梢詫?duì)Bitmap做幾乎任何改變,是的,你沒(méi)聽(tīng)錯(cuò),是任何,幾乎無(wú)所不能,這個(gè)屌毛方法我曾一度懷疑谷歌那些逗比為何將它屈尊在Canvas下,因?yàn)樗鼘?duì)Bitmap的處理實(shí)在在強(qiáng)大了。上一節(jié)我們?cè)谥v到Matrix的時(shí)候說(shuō)過(guò)Matrix可以對(duì)我們的圖像做多種變換,實(shí)際上drawBitmapMesh也可以,只不過(guò)需要一點(diǎn)計(jì)算,比如我們可以使用drawBitmapMesh來(lái)模擬錯(cuò)切skew的效果。
- Canvas(Bitmap bitmap);含參數(shù)的構(gòu)造。
可以實(shí)現(xiàn)在一張Bitmap的基礎(chǔ)上進(jìn)行繪制。- canvas.setBitmap(Bitmap bitmap); 作用同含參數(shù)的構(gòu)造.
例如:
ivMain = (ImageView) findViewById(R.id.main_iv);
Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.RED);
ivMain.setImageBitmap(bitmap);
- canvas.translate()和rotate()方法:
此類方法是對(duì)畫(huà)布進(jìn)行平移旋轉(zhuǎn)等操作。其實(shí)可以理解為對(duì)坐標(biāo)軸的旋轉(zhuǎn)平移等操作。
-canvas.clipXXX()方法:對(duì)畫(huà)布的一種剪切方式,剪切后只能在剪切的部分顯示需要繪制的內(nèi)容。當(dāng)前畫(huà)布被“裁剪”了,只有剪裁的部分能夠出現(xiàn)我們繪制的內(nèi)容,如果我們所繪制的東西在該區(qū)域外部,即便繪制了你也看不到
clipPath(Path path, Region.Op op)
clipRect(Rect rect, Region.Op op)
clipRect(RectF rect, Region.Op op)
clipRect(float left, float top, float right, float bottom, Region.Op op)
clipRegion(Region region, Region.Op op)
Canvas中有關(guān)裁剪的方法,你會(huì)發(fā)現(xiàn)有一大堆帶有Region.Op參數(shù)的重載方法.要明白這些方法的Region.Op參數(shù)那么首先要了解Region為何物。Region的意思是“區(qū)域”,在Android里呢它同樣表示的是一塊封閉的區(qū)域。
詳情請(qǐng)看 一下8中有關(guān)Region的簡(jiǎn)介
-canvas.drawPath(Path path, Paint paint) 繪制路徑。
-canvas.drawTextOnPath (String text, Path path, float hOffset, float vOffset, Paint paint) ; 繪制文字在Path路徑上。
6 Rect和RectF類
Rect和RectF是類似的,只不過(guò)RectF中涉及計(jì)算的時(shí)候數(shù)值類型均為float型,兩者均表示一塊規(guī)則矩形。
重要的方法:
- intersect(RectF rectF) / intersect (float left, float top, float right, float bottom) :此方法表示兩個(gè)矩形相交的部分。取兩個(gè)區(qū)域的相交區(qū)域作為最終區(qū)域。
intersect方法的計(jì)算方式是相當(dāng)有趣的,它不是單純地計(jì)算相交而是去計(jì)算相交區(qū)域最近的左上端點(diǎn)和最近的右下端點(diǎn)
public class CanvasView extends View {
private Rect mRect;
public CanvasView(Context context, AttributeSet attrs) {
super(context, attrs);
mRect = new Rect(0, 0, 500, 500);
mRect.intersect(250, 250, 750, 750);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLUE);
canvas.clipRect(mRect);
canvas.drawColor(Color.RED);
}
注意:黃色線框?yàn)楹笃诩由系妮o助線非程序生成
- union(RectF rect) / union(float left, float top, float right, float bottom) 方法:
union方法與intersect相反,取的是相交區(qū)域最遠(yuǎn)的左上端點(diǎn)作為新區(qū)域的左上端點(diǎn),而取最遠(yuǎn)的右下端點(diǎn)作為新區(qū)域的右下端點(diǎn)
- mRect.union(250, 250, 750, 750);
運(yùn)行后我們會(huì)看到如下結(jié)果:
是不是覺(jué)得不是我們想象中的那樣單純地兩個(gè)區(qū)域相加。此方法是指的左上角的點(diǎn)和右下角的點(diǎn)的最遠(yuǎn)距離。
7 Path 類
此類表示一個(gè)路徑
- lineTo(float x, float y): 將路徑連接至某個(gè)點(diǎn)坐標(biāo)。(不適用moveTo方法時(shí)默認(rèn)起點(diǎn)坐標(biāo)為原點(diǎn))。
我們可以考慮多次調(diào)用lineTo方法來(lái)繪制更復(fù)雜的圖形.
- moveTo(float x, float y):將Path的起始點(diǎn)移動(dòng)到某個(gè)特定的點(diǎn)。(Path默認(rèn)起始點(diǎn)為原點(diǎn))
- close() 此方法含義師閉合曲線。
// 實(shí)例化路徑
mPath = new Path();
// 移動(dòng)點(diǎn)至[300,300]
mPath.moveTo(100, 100);
// 連接路徑到點(diǎn)
mPath.lineTo(300, 100);
mPath.lineTo(400, 200);
mPath.lineTo(200, 200);
// 閉合曲線
mPath.close();
- XXXTo() 貝塞爾曲線相關(guān)方法
這些方法幫助我們繪制各類直線、曲線
-- quadTo(float x1, float y1, float x2, float y2) 繪制二階貝塞爾曲線。quadTo的前兩個(gè)參數(shù)為控制點(diǎn)的坐標(biāo),后兩個(gè)參數(shù)為終點(diǎn)坐標(biāo), 當(dāng)然起點(diǎn)坐標(biāo)就是path的起點(diǎn)坐標(biāo)
-- cubicTo(float x1, float y1, float x2, float y2, float x3, float y3) 繪制三階貝塞爾曲線。與quadTo類似,前四個(gè)參數(shù)表示兩個(gè)控制點(diǎn),最后兩個(gè)參數(shù)表示終點(diǎn):
// 實(shí)例化路徑
mPath = new Path();
// 移動(dòng)點(diǎn)至[100,100]
mPath.moveTo(100, 100);
// 連接路徑到點(diǎn)
mPath.cubicTo(200, 200, 300, 0, 400, 100);
- arcTo (RectF oval, float startAngle, float sweepAngle) 用來(lái)生成弧線的方法。說(shuō)白了就是從圓或者橢圓上截取一部分而已。
// 實(shí)例化路徑
mPath = new Path();
// 移動(dòng)點(diǎn)至[100,100]
mPath.moveTo(100, 100);
// 連接路徑到點(diǎn)
RectF oval = new RectF(100, 100, 200, 200);
mPath.arcTo(oval, 0, 90);
運(yùn)行后效果跟我們想想的有點(diǎn)不一樣,
這是因?yàn)槭褂肞ath生成的路徑必定都是連貫的,雖然我們使用arcTo繪制的時(shí)一段狐,但是其最終都會(huì)與我們Path的起點(diǎn)鏈接起來(lái)。如果你不想要鏈接,那么path也提供了一種方法,而已設(shè)置是否強(qiáng)制鏈接起點(diǎn)。
arcTo (RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo) 該方法只是多了一個(gè)布爾值,值為true時(shí)將會(huì)把弧的起點(diǎn)作為Path的起點(diǎn)
Path中除了上面介紹的幾個(gè)XXXTo方法外還有一套rXXXTo方法:
rCubicTo(float x1, float y1, float x2, float y2, float x3, float y3)
rLineTo(float dx, float dy)
rMoveTo(float dx, float dy)
rQuadTo(float dx1, float dy1, float dx2, float dy2)
這一系列rXXXTo方法其實(shí)跟上面的那些XXXTo差不多的,唯一的不同是rXXXTo方法的參考坐標(biāo)是相對(duì)的而XXXTo方法的參考坐標(biāo)始終是參照畫(huà)布原點(diǎn)坐標(biāo)。相對(duì)的指的是,終點(diǎn)的坐標(biāo)是相對(duì)于起點(diǎn)的坐標(biāo)的,例如rMoveTo(100,100) ; rLineTo(200,200) ,表示這個(gè)線段的長(zhǎng)度是200而不是100.
- addXXX()方法,Path的這一系列的add方法允許我們直接往Path中添加一些曲線。
比如:addArc(RectF oval, float startAngle, float sweepAngle) 方法允許我們將一段弧形添加至Path,注意這里我用到了“添加”這個(gè)詞匯,也就是說(shuō),通過(guò)addXXX方法添加到Path中的曲線是不會(huì)和上一次的曲線進(jìn)行連接的。
-- 除了addArc(RectF oval, float startAngle, float sweepAngle)方法之外還有這一系列的add方法。
addCircle(float x, float y, float radius, Path.Direction dir)
addOval(float left, float top, float right, float bottom, Path.Direction dir)
addRect(float left, float top, float right, float bottom, Path.Direction dir)
addRoundRect(float left, float top, float right, float bottom, float rx, float ry, Path.Direction dir)
這些方法和addArc有很明顯的區(qū)別,就是多了一個(gè)Path.Direction參數(shù)Path.Direction只有兩個(gè)常量值CCW和CW分別表示逆時(shí)針?lè)较蜷]合和順時(shí)針?lè)较蜷]合
mPath.addOval(oval, Path.Direction.CW);
順時(shí)針
mPath.addOval(oval, Path.Direction.CCW);
逆時(shí)針public class PathView extends View {
private Path mPath;// 路徑對(duì)象
private Paint mPaint;// 路徑畫(huà)筆對(duì)象
public PathView(Context context, AttributeSet attrs) {
super(context, attrs);
/*
* 實(shí)例化畫(huà)筆并設(shè)置屬性
*/
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.CYAN);
mPaint.setStrokeWidth(5);
// 實(shí)例化路徑
mPath = new Path();
// 移動(dòng)點(diǎn)至[100,100]
mPath.moveTo(100, 100);
// 連接路徑到點(diǎn)
mPath.lineTo(200, 200);
// 添加一條弧線到Path中
RectF oval = new RectF(100, 100, 300, 400);
mPath.addArc(oval, 0, 90);
}
@Override
protected void onDraw(Canvas canvas) {
// 繪制路徑
canvas.drawPath(mPath, mPaint);
}
}
8 Region
回顧C(jī)anvas中有關(guān)裁剪的方法,你會(huì)發(fā)現(xiàn)有一大堆帶有Region.Op參數(shù)的重載方法:
clipPath(Path path, Region.Op op) clipRect(Rect rect, Region.Op op) clipRect(RectF rect, Region.Op op) clipRect(float left, float top, float right, float bottom, Region.Op op) clipRegion(Region region, Region.Op op)
要明白這些方法的Region.Op參數(shù)那么首先要了解Region為何物。Region的意思是“區(qū)域”,在Android里呢它同樣表示的是一塊封閉的區(qū)域,Region中的方法都非常的簡(jiǎn)單,我們重點(diǎn)來(lái)瞧瞧Region.Op,Op是Region的一個(gè)枚舉類,里面呢有六個(gè)枚舉常量:
那么Region.Op究竟有什么用呢?其實(shí)它就是個(gè)組合模式,我們?cè)鴮W(xué)過(guò)一個(gè)叫圖形混合模式的,而在本節(jié)開(kāi)頭我們也曾講過(guò)Rect也有類似的組合方法,Region.Op灰常簡(jiǎn)單,如果你看過(guò)圖形混合模式的話。這里我就給出一段測(cè)試代碼,大家可以嘗試去改變不同的組合模式看看效果
public class CanvasView extends View {
private Region mRegionA, mRegionB;// 區(qū)域A和區(qū)域B對(duì)象
private Paint mPaint;// 繪制邊框的Paint
public CanvasView(Context context, AttributeSet attrs) {
super(context, attrs);
// 實(shí)例化畫(huà)筆并設(shè)置屬性
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.WHITE);
mPaint.setStrokeWidth(2);
// 實(shí)例化區(qū)域A和區(qū)域B
mRegionA = new Region(100, 100, 300, 300);
mRegionB = new Region(200, 200, 400, 400);
}
@Override
protected void onDraw(Canvas canvas) {
// 填充顏色
canvas.drawColor(Color.BLUE);
canvas.save();
// 裁剪區(qū)域A
canvas.clipRegion(mRegionA);
// 再通過(guò)組合方式裁剪區(qū)域B
canvas.clipRegion(mRegionB, Region.Op.DIFFERENCE);
// 填充顏色
canvas.drawColor(Color.RED);
canvas.restore();
// 繪制框框幫助我們觀察
canvas.drawRect(100, 100, 300, 300, mPaint);
canvas.drawRect(200, 200, 400, 400, mPaint);
}
}
以下是各種組合模式的效果
DIFFERENCE
最終區(qū)域?yàn)榈谝粋€(gè)區(qū)域與第二個(gè)區(qū)域不同的區(qū)域。
INTERSECT
最終區(qū)域?yàn)榈谝粋€(gè)區(qū)域與第二個(gè)區(qū)域相交的區(qū)域。
REPLACE
最終區(qū)域?yàn)榈诙€(gè)區(qū)域。
REVERSE_DIFFERENCE
最終區(qū)域?yàn)榈诙€(gè)區(qū)域與第一個(gè)區(qū)域不同的區(qū)域。
UNION
最終區(qū)域?yàn)榈谝粋€(gè)區(qū)域加第二個(gè)區(qū)域。
XOR
最終區(qū)域?yàn)榈谝粋€(gè)區(qū)域加第二個(gè)區(qū)域并減去兩者相交的區(qū)域。
Region.Op就是這樣,它和我們之前講到的圖形混合模式幾乎一模一樣換湯不換藥……我在做示例的時(shí)候僅僅是使用了一個(gè)Region,實(shí)際上Rect、Cricle、Ovel等封閉的曲線都可以使用Region.Op,介于篇幅,而且也不難以理解就不多說(shuō)了。
有些童鞋會(huì)問(wèn)那么Region和Rect有什么區(qū)別呢?
首先最重要的一點(diǎn),Region表示的是一個(gè)區(qū)域,而Rect表示的是一個(gè)矩形,這是最根本的區(qū)別之一,其次,Region有個(gè)很特別的地方是它不受Canvas的變換影響,Canvas的local不會(huì)直接影響到Region自身,
什么意思呢?我們來(lái)看一個(gè)simple你就會(huì)明白:
public class CanvasView extends View {
private Region mRegion;// 區(qū)域?qū)ο?
private Rect mRect;// 矩形對(duì)象
private Paint mPaint;// 繪制邊框的Paint
public CanvasView(Context context, AttributeSet attrs) {
super(context, attrs);
// 實(shí)例化畫(huà)筆并設(shè)置屬性
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.DKGRAY);
mPaint.setStrokeWidth(2);
// 實(shí)例化矩形對(duì)象
mRect = new Rect(0, 0, 200, 200);
// 實(shí)例化區(qū)域?qū)ο?
mRegion = new Region(200, 200, 400, 400);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.save();
// 裁剪矩形
canvas.clipRect(mRect);
canvas.drawColor(Color.RED);
canvas.restore();
canvas.save();
// 裁剪區(qū)域
canvas.clipRegion(mRegion);
canvas.drawColor(Color.RED);
canvas.restore();
// 為畫(huà)布繪制一個(gè)邊框便于觀察
canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), mPaint);
}
}
大家看到,我在[0, 0, 200, 200]和[200, 200, 400, 400]的位置分別繪制了Rect和Region,它們兩個(gè)所占大小是一樣的:
畫(huà)布因?yàn)楹推聊灰粯哟螅瑂o~~我們看不出描邊的效果,這時(shí),我們將Canvas縮放至75%大小,看看會(huì)發(fā)生什么:
@Override
protected void onDraw(Canvas canvas) {
// 縮放畫(huà)布
canvas.scale(0.75F, 0.75F);
canvas.save();
// 裁剪矩形
canvas.clipRect(mRect);
canvas.drawColor(Color.RED);
canvas.restore();
canvas.save();
// 裁剪區(qū)域
canvas.clipRegion(mRegion);
canvas.drawColor(Color.RED);
canvas.restore();
// 為畫(huà)布繪制一個(gè)邊框便于觀察
canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), mPaint);
}
這時(shí)我們會(huì)看到,Rect隨著Canvas的縮放一起縮放了,但是Region依舊泰山不動(dòng)地淡定: