Android自定義控件(一)_2015-03-22

自定義控件教程:

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án)嘛……當(dāng)然不能填充不然就么意思了
         *
         * 畫筆樣式分三種:
         * 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)
    方法唆涝,該方法用來設(shè)置我們畫筆的筆觸風(fēng)格,上面的例子中我使用的是ROUND唇辨,表示是圓角的筆觸廊酣,那么什么叫筆觸呢,其實(shí)很簡單赏枚,就像我們現(xiàn)實(shí)世界中的筆亡驰,如果你用圓珠筆在紙上戳一點(diǎn),那么這個(gè)點(diǎn)一定是個(gè)圓饿幅,即便很小凡辱,它代表了筆的筆觸形狀,如果我們把一支鉛筆筆尖削成方形的栗恩,那么畫出來的線條會是一條彎曲的“矩形”透乾,這就是筆觸的意思。除了ROUND磕秤,Paint.Cap還提供了另外兩種類型:SQUARE和BUTT

  • setStrokeJoin(Paint.Join join)
    這個(gè)方法用于設(shè)置結(jié)合處的形態(tài)乳乌,就像上面的代碼中我們雖說是花了一條心電線,但是這條線其實(shí)是由無數(shù)條小線拼接成的市咆,拼接處的形狀就由該方法指定汉操。

  • setShadowLayer(float radius, float dx, float dy, int shadowColor)
    該方法為我們繪制的圖形添加一個(gè)陰影層效果:


TextPaint專門用戶繪制文字的畫筆

/* 
 * 初始化文字畫筆 
 */
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);

與畫筆顏色相關(guān)的類

詳情見博客:2,http://blog.csdn.net/aigestudio/article/details/41316141

PorterDuffXfermode類蒙兰,圖形混合模式的意思

2,View類的invalidate()方法,和postInvalidate()方法

在Android中提供了一個(gè)叫invalidate()的方法來讓我們重繪我們的View磷瘤。poistInvalidate()方法和invaliadate方法相同其弊,只是它可以在子線程中運(yùn)行.
nvalidate()方法只能在主線程中調(diào)用,而postInvalidate()方法可以在子線程中調(diào)用膀斋。

3,Shader類(著色器)

Paste_Image.png

Shader類呢也是個(gè)灰潮匝牛灰常簡單的類仰担,它有五個(gè)子類,像PathEffect一樣每個(gè)子類都實(shí)現(xiàn)了一種Shader绩社,Shader在三維軟件中我們稱之為著色器摔蓝,其作用嘛就像它的名字一樣是來給圖像著色的或者更通俗的說法是上色!這么說該懂了吧愉耙!再不懂去廁所哭去贮尉!這五個(gè)Shader里最異類的是BitmapShader,因?yàn)橹挥兴窃试S我們載入一張圖片來給圖像著色朴沿,那我們還是先來看看這個(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 畫布

  • canvas.save()览芳;鎖定畫布
  • canvas.restore(); 釋放畫布,即將畫布釋放到之前鎖定的位置鸿竖。先調(diào)用sava()方法沧竟,才能調(diào)用restore()方法進(jìn)行釋放。
    在Android中我們可以使用Canvas的saveXXX和restoreXXX方法來模擬圖層的類似效果

Canvas我們一直稱其為畫布缚忧,其實(shí)更準(zhǔn)確地說Canvas是一個(gè)容器悟泵,如果把Canvas理解成畫板,那么我們的“層”就像張張夾在畫板上的透明的紙搔谴,而這些紙對應(yīng)到Android則是一個(gè)個(gè)封裝在Canvas中的Bitmap魁袜。
除了save()方法Canvas還給我們提供了一系列的saveLayerXXX方法給我們保存畫布,與save()方法不同的是敦第,saveLayerXXX方法會將所有的操作存到一個(gè)新的Bitmap中而不影響當(dāng)前Canvas的Bitmap峰弹,而save()方法則是在當(dāng)前的Bitmap中進(jìn)行操作,并且只能針對Bitmap的形變和裁剪進(jìn)行操作芜果,saveLayerXXX方法則無所不能鞠呈,當(dāng)然兩者還有很多的不同.
save和saveLayerXXX方法有著本質(zhì)的區(qū)別,saveLayerXXX方法會將所有操作在一個(gè)新的Bitmap中進(jìn)行右钾,而save則是依靠stack棧來進(jìn)行
詳情:http://blog.csdn.net/aigestudio/article/details/42677973

  • canvas.translate(x, y);平移畫布蚁吝,就相當(dāng)于將畫布的原點(diǎn)移到x,y的位置 旱爆,即相當(dāng)于坐標(biāo)系移動了。
Paste_Image.png
  • canvas.rotate(degrees);旋轉(zhuǎn)畫布窘茁,將畫布按照一定角度進(jìn)行旋轉(zhuǎn)怀伦,即相當(dāng)于坐標(biāo)系進(jìn)行了旋轉(zhuǎn)。
Paste_Image.png

注意:畫布的平移旋轉(zhuǎn)同樣也會影響畫布的自身坐標(biāo)

5山林,Canvas類(畫布)


Canvas所提供的各種方法根據(jù)功能來看大致可以分為幾類房待,第一是以drawXXX為主的繪制方法,第二是以clipXXX為主的裁剪方法驼抹,第三是以scale桑孩、skew、translate和rotate組成的Canvas變換方法框冀,最后一類則是以saveXXX和restoreXXX構(gòu)成的畫布鎖定和還原流椒。

  • 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è)很屌毛的方法温数,為什么這樣說呢安岂?因?yàn)樗梢詫itmap做幾乎任何改變,是的帆吻,你沒聽錯域那,是任何,幾乎無所不能猜煮,這個(gè)屌毛方法我曾一度懷疑谷歌那些逗比為何將它屈尊在Canvas下次员,因?yàn)樗鼘itmap的處理實(shí)在在強(qiáng)大了。上一節(jié)我們在講到Matrix的時(shí)候說過Matrix可以對我們的圖像做多種變換王带,實(shí)際上drawBitmapMesh也可以淑蔚,只不過需要一點(diǎn)計(jì)算,比如我們可以使用drawBitmapMesh來模擬錯切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()方法:
    此類方法是對畫布進(jìn)行平移旋轉(zhuǎn)等操作搞挣。其實(shí)可以理解為對坐標(biāo)軸的旋轉(zhuǎn)平移等操作带迟。
    -canvas.clipXXX()方法:對畫布的一種剪切方式,剪切后只能在剪切的部分顯示需要繪制的內(nèi)容囱桨。當(dāng)前畫布被“裁剪”了,只有剪裁的部分能夠出現(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)裁剪的方法舍肠,你會發(fā)現(xiàn)有一大堆帶有Region.Op參數(shù)的重載方法.要明白這些方法的Region.Op參數(shù)那么首先要了解Region為何物搀继。Region的意思是“區(qū)域”窘面,在Android里呢它同樣表示的是一塊封閉的區(qū)域。
詳情請看 一下8中有關(guān)Region的簡介
-canvas.drawPath(Path path, Paint paint) 繪制路徑叽躯。
-canvas.drawTextOnPath (String text, Path path, float hOffset, float vOffset, Paint paint) ; 繪制文字在Path路徑上财边。

6 Rect和RectF類

Rect和RectF是類似的,只不過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);  
    }  

圖示.png

注意:黃色線框?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)行后我們會看到如下結(jié)果:

Paste_Image.png

是不是覺得不是我們想象中的那樣單純地兩個(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方法來繪制更復(fù)雜的圖形.
  • moveTo(float x, float y):將Path的起始點(diǎn)移動到某個(gè)特定的點(diǎn)甘磨。(Path默認(rèn)起始點(diǎn)為原點(diǎn))
  • close() 此方法含義師閉合曲線橡羞。
// 實(shí)例化路徑  
mPath = new Path();    
// 移動點(diǎn)至[300,300]  
mPath.moveTo(100, 100);    
// 連接路徑到點(diǎn)  
mPath.lineTo(300, 100);  
mPath.lineTo(400, 200);  
mPath.lineTo(200, 200);    
// 閉合曲線  
mPath.close(); 
Paste_Image.png
  • 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();    
// 移動點(diǎn)至[100,100]  
mPath.moveTo(100, 100);    
// 連接路徑到點(diǎn)  
mPath.cubicTo(200, 200, 300, 0, 400, 100);  
三階貝塞爾曲線.png
  • arcTo (RectF oval, float startAngle, float sweepAngle) 用來生成弧線的方法。說白了就是從圓或者橢圓上截取一部分而已椎侠。
// 實(shí)例化路徑  
mPath = new Path();    
// 移動點(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)行后.png

運(yùn)行后效果跟我們想想的有點(diǎn)不一樣第租,這是因?yàn)槭褂肞ath生成的路徑必定都是連貫的,雖然我們使用arcTo繪制的時(shí)一段狐我纪,但是其最終都會與我們Path的起點(diǎn)鏈接起來慎宾。如果你不想要鏈接,那么path也提供了一種方法浅悉,而已設(shè)置是否強(qiáng)制鏈接起點(diǎn)趟据。

  • arcTo (RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo) 該方法只是多了一個(gè)布爾值,值為true時(shí)將會把弧的起點(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)是相對的而XXXTo方法的參考坐標(biāo)始終是參照畫布原點(diǎn)坐標(biāo)之宿。相對的指的是,終點(diǎn)的坐標(biāo)是相對于起點(diǎn)的坐標(biāo)的苛坚,例如rMoveTo(100,100) ; rLineTo(200,200) ,表示這個(gè)線段的長度是200而不是100.

  • addXXX()方法比被,Path的這一系列的add方法允許我們直接往Path中添加一些曲線色难。
    比如:addArc(RectF oval, float startAngle, float sweepAngle) 方法允許我們將一段弧形添加至Path,注意這里我用到了“添加”這個(gè)詞匯等缀,也就是說枷莉,通過addXXX方法添加到Path中的曲線是不會和上一次的曲線進(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í)針方向閉合和順時(shí)針方向閉合
mPath.addOval(oval, Path.Direction.CW);順時(shí)針

Paste_Image.png

mPath.addOval(oval, Path.Direction.CCW); 逆時(shí)針
Paste_Image.png

public class PathView extends View {  
    private Path mPath;// 路徑對象  
    private Paint mPaint;// 路徑畫筆對象  
  
    public PathView(Context context, AttributeSet attrs) {  
        super(context, attrs);    
        /* 
         * 實(shí)例化畫筆并設(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();    
        // 移動點(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);  
    }  
} 
Paste_Image.png

8 Region

回顧C(jī)anvas中有關(guān)裁剪的方法,你會發(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中的方法都非常的簡單膳音,我們重點(diǎn)來瞧瞧Region.Op召衔,Op是Region的一個(gè)枚舉類,里面呢有六個(gè)枚舉常量:

Paste_Image.png

那么Region.Op究竟有什么用呢祭陷?其實(shí)它就是個(gè)組合模式苍凛,我們曾學(xué)過一個(gè)叫圖形混合模式的,而在本節(jié)開頭我們也曾講過Rect也有類似的組合方法兵志,Region.Op灰常簡單醇蝴,如果你看過圖形混合模式的話。這里我就給出一段測試代碼想罕,大家可以嘗試去改變不同的組合模式看看效果

public class CanvasView extends View {  
    private Region mRegionA, mRegionB;// 區(qū)域A和區(qū)域B對象  
    private Paint mPaint;// 繪制邊框的Paint  
  
    public CanvasView(Context context, AttributeSet attrs) {  
        super(context, attrs);    
        // 實(shí)例化畫筆并設(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);    
        // 再通過組合方式裁剪區(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,介于篇幅茅信,而且也不難以理解就不多說了盾舌。
有些童鞋會問那么Region和Rect有什么區(qū)別呢?
首先最重要的一點(diǎn)蘸鲸,Region表示的是一個(gè)區(qū)域妖谴,而Rect表示的是一個(gè)矩形,這是最根本的區(qū)別之一,其次膝舅,Region有個(gè)很特別的地方是它不受Canvas的變換影響嗡载,Canvas的local不會直接影響到Region自身,
什么意思呢仍稀?我們來看一個(gè)simple你就會明白:

public class CanvasView extends View {  
    private Region mRegion;// 區(qū)域?qū)ο? 
    private Rect mRect;// 矩形對象  
    private Paint mPaint;// 繪制邊框的Paint  
  
    public CanvasView(Context context, AttributeSet attrs) {  
        super(context, attrs);  
  
        // 實(shí)例化畫筆并設(shè)置屬性  
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);  
        mPaint.setStyle(Paint.Style.STROKE);  
        mPaint.setColor(Color.DKGRAY);  
        mPaint.setStrokeWidth(2);  
  
        // 實(shí)例化矩形對象  
        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();  
  
        // 為畫布繪制一個(gè)邊框便于觀察  
        canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), mPaint);  
    }  
}  

大家看到洼滚,我在[0, 0, 200, 200]和[200, 200, 400, 400]的位置分別繪制了Rect和Region,它們兩個(gè)所占大小是一樣的:



畫布因?yàn)楹推聊灰粯哟蠹寂耍瑂o~~我們看不出描邊的效果遥巴,這時(shí),我們將Canvas縮放至75%大小享幽,看看會發(fā)生什么:

@Override  
protected void onDraw(Canvas canvas) {  
    // 縮放畫布  
    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();  
  
    // 為畫布繪制一個(gè)邊框便于觀察  
    canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), mPaint);  
}  

這時(shí)我們會看到铲掐,Rect隨著Canvas的縮放一起縮放了,但是Region依舊泰山不動地淡定:


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末值桩,一起剝皮案震驚了整個(gè)濱河市摆霉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌颠毙,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件砂碉,死亡現(xiàn)場離奇詭異蛀蜜,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)增蹭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門滴某,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人滋迈,你說我怎么就攤上這事霎奢。” “怎么了饼灿?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵幕侠,是天一觀的道長。 經(jīng)常有香客問我碍彭,道長晤硕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任庇忌,我火速辦了婚禮舞箍,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘皆疹。我一直安慰自己疏橄,他們只是感情好飘痛,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著脐嫂,像睡著了一般澳叉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上立砸,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天掖疮,我揣著相機(jī)與錄音,去河邊找鬼颗祝。 笑死浊闪,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的螺戳。 我是一名探鬼主播搁宾,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼倔幼!你這毒婦竟也來了盖腿?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤损同,失蹤者是張志新(化名)和其女友劉穎翩腐,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體膏燃,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡茂卦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了组哩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片等龙。...
    茶點(diǎn)故事閱讀 38,018評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖伶贰,靈堂內(nèi)的尸體忽然破棺而出蛛砰,到底是詐尸還是另有隱情,我是刑警寧澤黍衙,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布泥畅,位于F島的核電站,受9級特大地震影響琅翻,放射性物質(zhì)發(fā)生泄漏涯捻。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一望迎、第九天 我趴在偏房一處隱蔽的房頂上張望障癌。 院中可真熱鬧,春花似錦辩尊、人聲如沸涛浙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽轿亮。三九已至疮薇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間我注,已是汗流浹背按咒。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留但骨,地道東北人励七。 一個(gè)月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像奔缠,于是被迫代替她去往敵國和親掠抬。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評論 2 345

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