Android Canvas方法總結(jié)最全面詳解API(二)

本節(jié)引言:

本節(jié)繼續(xù)帶來Android繪圖系列詳解之Canvas API詳解(Part 2)仁堪,今天要講解的是Canvas 中的ClipXxx方法族泽谨!我們可以看到文檔中給我們提供的Clip方法有三種類型: clipPath( )艾猜,clipRect( )姑裂,clipRegion( )糟秘;
通過Path,Rect旨巷,Region的不同組合巨缘,幾乎可以支持任意形狀的裁剪區(qū)域!

  • Path:可以是開放或閉合的曲線采呐,線構(gòu)成的復(fù)雜的集合圖形
  • Rect:矩形區(qū)域
  • Region:可以理解為區(qū)域組合若锁,比如可以將兩個(gè)區(qū)域相加,相減斧吐,并又固,疑惑等!

1.Region.Op組合方式詳解

其實(shí)難點(diǎn)無非這個(gè)煤率,Region代表著區(qū)域仰冠,表示的是Canvas圖層上的某一塊封閉區(qū)域! 當(dāng)然蝶糯,有時(shí)間你可以自己慢慢去扣這個(gè)類洋只,而我們一般關(guān)注的只是他的一個(gè)枚舉值:Op

下面我們來看看個(gè)個(gè)枚舉值所起的作用: 我們假設(shè)兩個(gè)裁剪區(qū)域A和B,那么我們調(diào)用Region.Op對(duì)應(yīng)的枚舉值:

  • DIFFERENCE:A和B的差集范圍,即A - B木张,只有在此范圍內(nèi)的繪制內(nèi)容才會(huì)被顯示;
  • INTERSECT:即A和B的交集范圍端三,只有在此范圍內(nèi)的繪制內(nèi)容才會(huì)被顯示
  • UNION:即A和B的并集范圍舷礼,即兩者所包括的范圍的繪制內(nèi)容都會(huì)被顯示;
  • XOR:A和B的補(bǔ)集范圍郊闯,此例中即A除去B以外的范圍妻献,只有在此范圍內(nèi)的繪制內(nèi)容才會(huì)被顯示;
  • REVERSE_DIFFERENCE:B和A的差集范圍团赁,即B - A育拨,只有在此范圍內(nèi)的繪制內(nèi)容才會(huì)被顯示;
  • REPLACE:不論A和B的集合狀況欢摄,B的范圍將全部進(jìn)行顯示熬丧,如果和A有交集,則將覆蓋A的交集范圍怀挠;
Paste_Image.png

如果你學(xué)過集合析蝴,那么畫個(gè)Venn(韋恩圖)就一清二楚了,沒學(xué)過绿淋?沒事闷畸,我們寫個(gè)例子來試試 對(duì)應(yīng)的結(jié)果~!寫個(gè)初始化畫筆以及畫矩形的方法:

private void init() {
    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setStrokeWidth(6);
    mPaint.setColor(getResources().getColor(R.color.blush));
}

private void drawScene(Canvas canvas){
    canvas.drawRect(0, 0, 200, 200, mPaint);
}

Op.DIFFERENCE:

canvas.clipRect(10, 10, 110, 110);        //第一個(gè)
canvas.clipRect(50, 50, 150, 150, Region.Op.DIFFERENCE); //第二個(gè)
drawScene(canvas);

先后在(10,10)以及(50,50)為起點(diǎn)吞滞,裁剪了兩個(gè)100*100的矩形佑菩,得出的裁剪結(jié)果是:
A和B的差集 = A - (A和B相交的部分)

Op.INTERSECT:

canvas.clipRect(10, 10, 110, 110);        //第一個(gè)
canvas.clipRect(50, 50, 150, 150, Region.Op.INTERSECT); //第二個(gè)
drawScene(canvas);

結(jié)果

先后在(10,10)以及(50,50)為起點(diǎn),裁剪了兩個(gè)100*100的矩形裁赠,得出的裁剪結(jié)果是:
A和B的交集 = A和B相交的部分

Op.UNION:

canvas.clipRect(10, 10, 110, 110); //第一個(gè)
canvas.clipRect(40, 40, 140, 140, Region.Op.UNION); //第二個(gè)drawScene(canvas);

結(jié)果

先后在(10,10)以及(50,50)為起點(diǎn)殿漠,裁剪了兩個(gè)100*100的矩形,得出的裁剪結(jié)果是: A和B的并集 = A的區(qū)域 + B的區(qū)域

Op.XOR:

canvas.clipRect(10, 10, 110, 110);        //第一個(gè)
canvas.clipRect(50, 50, 150, 150, Region.Op.XOR); //第二個(gè)
drawScene(canvas);

結(jié)果

先后在(10,10)以及(50,50)為起點(diǎn)佩捞,裁剪了兩個(gè)100*100的矩形凸舵,得出的裁剪結(jié)果是:
A和B的補(bǔ)集 = A和B的合集 - A和B的交集

Op.REVERSE_DIFFERENCE:

canvas.clipRect(10, 10, 110, 110); //第一個(gè)
canvas.clipRect(50, 50, 150, 150, Region.Op.REVERSE_DIFFERENCE); //第二個(gè)
drawScene(canvas);
**結(jié)果**:

![](http://upload-images.jianshu.io/upload_images/7508328-5e53fa51cec15f9d.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

>先后在(10,10)以及(50,50)為起點(diǎn),裁剪了兩個(gè)100*100的矩形失尖,得出的裁剪結(jié)果是:
 **B和A的差集 = B - A和B的交集**
# Op.REPLACE:
```java
canvas.clipRect(10, 10, 110, 110); //第一個(gè)
canvas.clipRect(50, 50, 150, 150, Region.Op.REPLACE); //第二個(gè)
drawScene(canvas);

結(jié)果

先后在(10,10)以及(50,50)為起點(diǎn)啊奄,裁剪了兩個(gè)100*100的矩形,得出的裁剪結(jié)果是:
不論A和B的集合狀況掀潮,B的范圍將全部進(jìn)行顯示菇夸,如果和A有交集,則將覆蓋A的交集范圍仪吧;

2.clipRect方法詳解:

clipRect提供了七個(gè)重載方法:

參數(shù)介紹如下

  • rect:Rect對(duì)象庄新,用于定義裁剪區(qū)的范圍,Rect和RectF功能類似,精度和提供的方法不同而已
  • left:矩形裁剪區(qū)的左邊位置
  • top:矩形裁剪區(qū)的上邊位置
  • right:矩形裁剪區(qū)的右邊位置
  • bottom:矩形裁剪區(qū)的下邊位置
  • op:裁剪區(qū)域的組合方式
    上述四個(gè)值可以是浮點(diǎn)型或者整型

使用案例

mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(Color.BLACK);
mPaint.setTextSize(60);

canvas.translate(300,300);
canvas.clipRect(100, 100, 300, 300);                //設(shè)置顯示范圍
canvas.drawColor(Color.WHITE);                      //白色背景
canvas.drawText("雙11择诈,繼續(xù)吃我的狗糧...", 150, 300, mPaint); //繪制字符串

運(yùn)行結(jié)果

從上面的例子械蹋,不知道你發(fā)現(xiàn)了沒? clipRect會(huì)受Canvas變換的影響羞芍,白色區(qū)域是不花的區(qū)域哗戈,所以clipRect裁剪的是畫布, 而我們的繪制是在這個(gè)裁剪后的畫布上進(jìn)行的荷科!超過該區(qū)域的不顯示唯咬!

4.clipPath方法詳解:

相比起clipRect,clipPath就只有兩個(gè)重載方法畏浆,使用方法非常簡(jiǎn)單胆胰,自己繪制一個(gè)Paht然后 傳入即可!

使用示例
這里復(fù)用我們以前在ImageView那里寫的圓形ImageView的例子~
實(shí)現(xiàn)代碼
自定義ImageView:RoundImageView.java

public class RoundImageView extends ImageView {

    private Bitmap mBitmap;
    private Rect mRect = new Rect();
    private PaintFlagsDrawFilter pdf = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG);
    private Paint mPaint = new Paint();
    private Path mPath=new Path();
    public RoundImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }


    //傳入一個(gè)Bitmap對(duì)象
    public void setBitmap(Bitmap bitmap) {
        this.mBitmap = bitmap;
    }


    private void init() {
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
        mPaint.setAntiAlias(true);// 抗鋸尺
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if(mBitmap == null)
        {
            return;
        }
        mRect.set(0,0,getWidth(),getHeight());
        canvas.save();
        canvas.setDrawFilter(pdf);
        mPath.addCircle(getWidth() / 2, getWidth() / 2, getHeight() / 2, Path.Direction.CCW);
        canvas.clipPath(mPath, Region.Op.REPLACE);
        canvas.drawBitmap(mBitmap, null, mRect, mPaint);
        canvas.restore();
    }
}

運(yùn)行效果圖

另外使用該方法制作的圓角ImageView會(huì)有鋸齒明顯刻获,即使你為Paint蜀涨,Canvas設(shè)置了 抗鋸齒也沒用~假如你要求高的,可以使用Xfermode-PorterDuff設(shè)置圖像混排來實(shí)現(xiàn)蝎毡, 基本沒鋸齒

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末勉盅,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子顶掉,更是在濱河造成了極大的恐慌草娜,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,692評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件痒筒,死亡現(xiàn)場(chǎng)離奇詭異宰闰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)簿透,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門移袍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人老充,你說我怎么就攤上這事葡盗。” “怎么了啡浊?”我有些...
    開封第一講書人閱讀 162,995評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵觅够,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我巷嚣,道長(zhǎng)喘先,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,223評(píng)論 1 292
  • 正文 為了忘掉前任廷粒,我火速辦了婚禮窘拯,結(jié)果婚禮上红且,老公的妹妹穿的比我還像新娘。我一直安慰自己涤姊,他們只是感情好暇番,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著思喊,像睡著了一般壁酬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上搔涝,一...
    開封第一講書人閱讀 51,208評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音和措,去河邊找鬼庄呈。 笑死,一個(gè)胖子當(dāng)著我的面吹牛派阱,可吹牛的內(nèi)容都是我干的诬留。 我是一名探鬼主播,決...
    沈念sama閱讀 40,091評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼贫母,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼文兑!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起腺劣,我...
    開封第一講書人閱讀 38,929評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤绿贞,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后橘原,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體籍铁,經(jīng)...
    沈念sama閱讀 45,346評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評(píng)論 2 333
  • 正文 我和宋清朗相戀三年趾断,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了拒名。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,739評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡芋酌,死狀恐怖增显,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情脐帝,我是刑警寧澤同云,帶...
    沈念sama閱讀 35,437評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站堵腹,受9級(jí)特大地震影響梢杭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜秸滴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評(píng)論 3 326
  • 文/蒙蒙 一武契、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦咒唆、人聲如沸届垫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)装处。三九已至,卻和暖如春浸船,著一層夾襖步出監(jiān)牢的瞬間妄迁,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工李命, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留登淘,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,760評(píng)論 2 369
  • 正文 我出身青樓封字,卻偏偏與公主長(zhǎng)得像黔州,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子阔籽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評(píng)論 2 354

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