UI繪制(四)——Paint高級(jí)應(yīng)用

線帽

Paint.setStrokeCap(Paint.Cap.BUTT); 無線帽
Paint.setStrokeCap(Paint.Cap.ROUND); 圓形線帽
Paint.setStrokeCap(Paint.Cap.SQUARE);方形線帽

f18e0eb1379575428eefcd82d1216005.png

拐角風(fēng)格

Paint.setStrokeJoin(Paint.Join.MITER); 默認(rèn)
Paint.setStrokeJoin(Paint.Join.ROUND); 圓角
Paint.setStrokeJoin(Paint.Join.BEVEL); 斜角

ac20ae1c998fdb48a887833251739183.png

渲染器

線性渲染
        /**
         * 1.線性渲染,LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorInt int colors[], @Nullable float positions[], @NonNull TileMode tile)
         * (x0,y0):漸變起始點(diǎn)坐標(biāo)
         * (x1,y1):漸變結(jié)束點(diǎn)坐標(biāo)
         * color0:漸變開始點(diǎn)顏色,16進(jìn)制的顏色表示鹅巍,必須要帶有透明度
         * color1:漸變結(jié)束顏色
         * colors:漸變數(shù)組
         * positions:位置數(shù)組,position的取值范圍[0,1],作用是指定某個(gè)位置的顏色值,如果傳null,漸變就線性變化。
         * tile:用于指定控件區(qū)域大于指定的漸變區(qū)域時(shí),空白區(qū)域的顏色填充方法
         */
        mShader = new LinearGradient(0, 0, 200, 200, new int[]{Color.RED, Color.BLUE, Color.GREEN}, new float[]{0.f,0.7f,1}, Shader.TileMode.REPEAT);
        mPaint.setShader(mShader);
        canvas.drawRect(0,100,400,450, mPaint);
環(huán)形渲染
         /**
         * 環(huán)形渲染,RadialGradient(float centerX, float centerY, float radius, @ColorInt int colors[], @Nullable float stops[], TileMode tileMode)
         * centerX ,centerY:shader的中心坐標(biāo)墓陈,開始漸變的坐標(biāo)
         * radius:漸變的半徑
         * centerColor,edgeColor:中心點(diǎn)漸變顏色,邊界的漸變顏色
         * colors:漸變顏色數(shù)組
         * stoops:漸變位置數(shù)組第献,類似掃描漸變的positions數(shù)組贡必,取值[0,1],中心點(diǎn)為0,半徑到達(dá)位置為1.0f
         * tileMode:shader未覆蓋以外的填充模式庸毫。
         */
        mShader = new RadialGradient(650, 250, 150, new int[]{Color.GREEN, Color.YELLOW, Color.RED}, null, Shader.TileMode.CLAMP);
        mPaint.setShader(mShader);
        canvas.drawCircle(650, 250, 150, mPaint);
掃描渲染
        /**
         * 掃描渲染赊级,SweepGradient(float cx, float cy, @ColorInt int color0,int color1)
         * cx,cy 漸變中心坐標(biāo)
         * color0,color1:漸變開始結(jié)束顏色
         * colors,positions:類似LinearGradient,用于多顏色漸變,positions為null時(shí)岔绸,根據(jù)顏色線性漸變
         */
        mShader = new SweepGradient(1050, 250, Color.RED, Color.GREEN);
        mPaint.setShader(mShader);
        canvas.drawCircle(1050, 250, 150, mPaint);
位圖渲染
        /**
         * 位圖渲染,BitmapShader(@NonNull Bitmap bitmap, @NonNull TileMode tileX, @NonNull TileMode tileY)
         * Bitmap:構(gòu)造shader使用的bitmap
         * tileX:X軸方向的TileMode
         * tileY:Y軸方向的TileMode
            REPEAT, 繪制區(qū)域超過渲染區(qū)域的部分橡伞,重復(fù)排版
            CLAMP盒揉, 繪制區(qū)域超過渲染區(qū)域的部分,會(huì)以最后一個(gè)像素拉伸排版
            MIRROR, 繪制區(qū)域超過渲染區(qū)域的部分兑徘,鏡像翻轉(zhuǎn)排版
         */
        mShader = new BitmapShader(mBitmap, Shader.TileMode.REPEAT, Shader.TileMode.MIRROR);
        mPaint.setShader(mShader);
        canvas.drawRect(0,600,300, 800, mPaint);
組合渲染
        /**
         * 組合渲染刚盈,
         * ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, Xfermode mode)
         * ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, PorterDuff.Mode mode)
         * shaderA,shaderB:要混合的兩種shader
         * Xfermode mode: 組合兩種shader顏色的模式
         * PorterDuff.Mode mode: 組合兩種shader顏色的模式
         */
        BitmapShader bitmapShader = new BitmapShader(mBitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
        LinearGradient linearGradient = new LinearGradient(400, 600, 900, 1100, new int[]{Color.RED, Color.GREEN, Color.BLUE}, null, Shader.TileMode.CLAMP);
        mShader = new ComposeShader(bitmapShader, linearGradient, PorterDuff.Mode.MULTIPLY);
        mPaint.setShader(mShader);
        canvas.drawCircle(650, 850, 250, mPaint);
3911af3a313cbb49949fd720a935cae8.png

圖層混合模式

            // draw the border
            paint.setStyle(Paint.Style.STROKE);
            paint.setShader(null);
            canvas.drawRect(x - 0.5f, y - 0.5f, x + W + 0.5f, y + H + 0.5f, paint);

            // draw the checker-board pattern
            paint.setStyle(Paint.Style.FILL);
            paint.setShader(mBG);
            canvas.drawRect(x, y, x + W, y + H, paint);

            // 使用離屏繪制
            int sc = canvas.saveLayer(x, y, x + W, y + H, null);
            canvas.translate(x, y);
            canvas.drawBitmap(makeDst(2 * W / 3, 2 * H / 3), 0, 0, paint);
            paint.setXfermode(Xfermode.sModes[i]);
            canvas.drawBitmap(makeSrc(2 * W / 3, 2 * H / 3), W / 3, H / 3, paint);
            paint.setXfermode(null);
            canvas.restoreToCount(sc);
    //其中Sa全稱為Source alpha表示源圖的Alpha通道;Sc全稱為Source color表示源圖的顏色挂脑;Da全稱為Destination alpha表示目標(biāo)圖的Alpha通道藕漱;Dc全稱為Destination color表示目標(biāo)圖的顏色欲侮,[...,..]前半部分計(jì)算的是結(jié)果圖像的Alpha通道值,“,”后半部分計(jì)算的是結(jié)果圖像的顏色值肋联。
    //效果作用于src源圖像區(qū)域
    public static final PorterDuffXfermode[] sModes = {
            //所繪制不會(huì)提交到畫布上
            new PorterDuffXfermode(PorterDuff.Mode.CLEAR),
            //顯示上層繪制的圖像
            new PorterDuffXfermode(PorterDuff.Mode.SRC),
            //顯示下層繪制圖像
            new PorterDuffXfermode(PorterDuff.Mode.DST),
            //正常繪制顯示,上下層繪制疊蓋
            new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER),

            //上下層都顯示,下層居上顯示
            new PorterDuffXfermode(PorterDuff.Mode.DST_OVER),
            //取兩層繪制交集项秉,顯示上層
            new PorterDuffXfermode(PorterDuff.Mode.SRC_IN),
            //取兩層繪制交集稚机,顯示下層
            new PorterDuffXfermode(PorterDuff.Mode.DST_IN),
            //取上層繪制非交集部分,交集部分變成透明
            new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT),

            //取下層繪制非交集部分侮繁,交集部分變成透明
            new PorterDuffXfermode(PorterDuff.Mode.DST_OUT),
            //取上層交集部分與下層非交集部分
            new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP),
            //取下層交集部分與上層非交集部分
            new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP),
            //去除兩圖層交集部分
            new PorterDuffXfermode(PorterDuff.Mode.XOR),

            //取兩圖層全部區(qū)域虑粥,交集部分顏色加深
            new PorterDuffXfermode(PorterDuff.Mode.DARKEN),
            //取兩圖層全部區(qū)域,交集部分顏色點(diǎn)亮
            new PorterDuffXfermode(PorterDuff.Mode.LIGHTEN),
            //取兩圖層交集部分宪哩,顏色疊加
            new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY),
            //取兩圖層全部區(qū)域娩贷,交集部分濾色
            new PorterDuffXfermode(PorterDuff.Mode.SCREEN),

            //取兩圖層全部區(qū)域,交集部分飽和度相加
            new PorterDuffXfermode(PorterDuff.Mode.ADD),
            //取兩圖層全部區(qū)域锁孟,交集部分疊加
            new PorterDuffXfermode(PorterDuff.Mode.OVERLAY)
    };
e42db77c81b9b0438365428a3237b19b.png

顏色過濾器

LightingColorFilter
        /**
         * R' = R * mul.R / 0xff + add.R
         * G' = G * mul.G / 0xff + add.G
         * B' = B * mul.B / 0xff + add.B
         */
        int sc;
        //原始圖片效果
        sc = canvas.saveLayer(0, 0, W, H, null);
        canvas.drawText("原始圖片", 100,50,labelP);
        LightingColorFilter lighting1 = new LightingColorFilter(0xffffff,0x000000);
        mPaint.setColorFilter(lighting1);
        canvas.drawBitmap(mBitmap, 0,100, mPaint);
        canvas.restoreToCount(sc);

        //藍(lán)色去除掉
        sc = canvas.saveLayer(W, 0, W*2, H, null);
        canvas.translate(W, 0);
        canvas.drawText("藍(lán)色去除掉", 100,50,labelP);
        LightingColorFilter lighting2 = new LightingColorFilter(0xffff00,0x000000);
        mPaint.setColorFilter(lighting2);
        canvas.drawBitmap(mBitmap, 0,100, mPaint);
        canvas.restoreToCount(sc);

        //綠色更亮
        sc = canvas.saveLayer(W*2, 0, W*3, H, null);
        canvas.translate(W*2, 0);
        canvas.drawText("綠色更亮", 100,50,labelP);
        LightingColorFilter lighting3 = new LightingColorFilter(0xffffff,0x003000);
        mPaint.setColorFilter(lighting3);
        canvas.drawBitmap(mBitmap, 0,100, mPaint);
        canvas.restoreToCount(sc);
ba117e660fc9f943910e5a96d22341aa.png
PorterDuffColorFilter
        //圖層混合紅色
        sc = canvas.saveLayer(0, H, W, H*2, null);
        canvas.translate(0, H);
        canvas.drawText("圖層混合紅色", 100,50,labelP);
        PorterDuffColorFilter porterDuffColorFilter1 = new PorterDuffColorFilter(Color.RED, PorterDuff.Mode.DARKEN);
        mPaint.setColorFilter(porterDuffColorFilter1);
        canvas.drawBitmap(mBitmap, 0, 100, mPaint);
        canvas.restoreToCount(sc);

        //圖層混合黃色
        sc = canvas.saveLayer(W, H, W*2, H*2, null);
        canvas.translate(W, H);
        canvas.drawText("圖層混合黃色", 100,50,labelP);
        PorterDuffColorFilter porterDuffColorFilter2 = new PorterDuffColorFilter(Color.YELLOW, PorterDuff.Mode.DARKEN);
        mPaint.setColorFilter(porterDuffColorFilter2);
        canvas.drawBitmap(mBitmap, 0, 100, mPaint);
        canvas.restoreToCount(sc);

        //圖層混合紅色
        sc = canvas.saveLayer(W*2, H, W*3, H*2, null);
        canvas.translate(W*2, H);
        canvas.drawText("圖層混合紫色", 100,50,labelP);
        PorterDuffColorFilter porterDuffColorFilter3 = new PorterDuffColorFilter(Color.MAGENTA, PorterDuff.Mode.DARKEN);
        mPaint.setColorFilter(porterDuffColorFilter3);
        canvas.drawBitmap(mBitmap, 0, 100, mPaint);
        canvas.restoreToCount(sc);
54ad2658514f0140941d7176284c7801.png
ColorMatrixColorFilter
        float[] colorMatrix = {
                2,0,0,0,0,   //red
                0,1,0,0,0,   //green
                0,0,1,0,0,   //blue
                0,0,0,1,0    //alpha
        };

        sc = canvas.saveLayer(0, H*2, W, H*3, null);
        canvas.translate(0, H*2);
        canvas.drawText("顏色亮度調(diào)節(jié)-綠色", 100,50,labelP);
        ColorMatrix cm1 = new ColorMatrix();
//        //顏色亮度調(diào)節(jié)-綠色
        cm1.setScale(1,2,1,1);
        ColorMatrixColorFilter colorMatrixColorFilter1 = new ColorMatrixColorFilter(cm1);
        mPaint.setColorFilter(colorMatrixColorFilter1);
        canvas.drawBitmap(mBitmap, 0, 100, mPaint);
        canvas.restoreToCount(sc);


        sc = canvas.saveLayer(W, H*2, W*2, H*3, null);
        canvas.translate(W, H*2);
        canvas.drawText("飽和度調(diào)節(jié)", 100,50,labelP);
        ColorMatrix cm2 = new ColorMatrix();
//        //飽和度調(diào)節(jié)0-無色彩彬祖, 1- 默認(rèn)效果, >1飽和度加強(qiáng)
        cm2.setSaturation(2);
        ColorMatrixColorFilter colorMatrixColorFilter2 = new ColorMatrixColorFilter(cm2);
        mPaint.setColorFilter(colorMatrixColorFilter2);
        canvas.drawBitmap(mBitmap, 0, 100, mPaint);
        canvas.restoreToCount(sc);



        sc = canvas.saveLayer(W*2, H*2, W*3, H*3, null);
        canvas.translate(W*2, H*2);
        canvas.drawText("色調(diào)調(diào)節(jié)", 100,50,labelP);
        ColorMatrix cm3 = new ColorMatrix();
        //色調(diào)調(diào)節(jié)-紅色45度
        cm3.setRotate(0, 45);
        ColorMatrixColorFilter colorMatrixColorFilter3 = new ColorMatrixColorFilter(cm3);
        mPaint.setColorFilter(colorMatrixColorFilter3);
        canvas.drawBitmap(mBitmap, 0, 100, mPaint);
        canvas.restoreToCount(sc);
19bb619b815f494e90acffd13312478a.png

遮罩濾鏡

        int W = 700;
        int H = 150;
        int sc;

        sc = canvas.saveLayer(0, 0, W, H, null);
        canvas.translate(0, 0);
        canvas.drawText("內(nèi)外模糊", 100,50,labelP);
        mPaint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.NORMAL));//設(shè)置畫筆遮罩濾鏡 ,傳入度數(shù)和樣式
        canvas.drawLine(100,100,W-100,100,mPaint);
        canvas.restoreToCount(sc);

        sc = canvas.saveLayer(0, H, W, H*2, null);
        canvas.translate(0, H);
        canvas.drawText("外模糊內(nèi)填充", 100,50,labelP);
        mPaint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.SOLID));//設(shè)置畫筆遮罩濾鏡 ,傳入度數(shù)和樣式
        canvas.drawLine(100,100,W-100,100,mPaint);
        canvas.restoreToCount(sc);

        sc = canvas.saveLayer(0, H*2, W, H*3, null);
        canvas.translate(0, H*2);
        canvas.drawText("外模糊", 100,50,labelP);
        mPaint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.OUTER));//設(shè)置畫筆遮罩濾鏡 ,傳入度數(shù)和樣式
        canvas.drawLine(100,100,W-100,100,mPaint);
        canvas.restoreToCount(sc);

        sc = canvas.saveLayer(0, H*3, W, H*4, null);
        canvas.translate(0, H*3);
        canvas.drawText("內(nèi)模糊", 100,50,labelP);
        mPaint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.INNER));//設(shè)置畫筆遮罩濾鏡 ,傳入度數(shù)和樣式
        canvas.drawLine(100,100,W-100,100,mPaint);
        canvas.restoreToCount(sc);

        sc = canvas.saveLayer(0, H*4, W+300, H*4+500, null);
        canvas.translate(0, H*4);
        canvas.drawText("圖片加陰影", 100,50,labelP);
        Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.girl);
        // 獲取位圖的Alpha通道圖
        Bitmap shadowBitmap = mBitmap.extractAlpha();
        mPaint.setColor(Color.DKGRAY);
        // 設(shè)置畫筆遮罩濾鏡 ,傳入度數(shù)和樣式
        mPaint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.NORMAL));
        // 先繪制陰影
        canvas.drawBitmap(shadowBitmap, 100, 100, mPaint);
        // 畫原圖
        canvas.drawBitmap(mBitmap, 100, 100, null);
        canvas.restoreToCount(sc);
5f6e4219e2cf324181dd9a238382b854.png

測量文本寬度

    private void drawMeasureText(Canvas canvas) {
        mPaint.reset();
        mPaint.setColor(Color.BLACK);
        String str = "測試文本的長度:";
        Rect rect = new Rect();
        float size = 0;

        mPaint.setTextSize(10);
        mPaint.getTextBounds(str, 0, str.length(), rect); //測量文本大小罗岖,將文本大小信息存放在rect中
        size = mPaint.measureText(str);//獲取文本的寬
        canvas.drawText(str + size, 100, 100, mPaint);

        mPaint.setTextSize(20);
        mPaint.getTextBounds(str, 0, str.length(), rect); //測量文本大小涧至,將文本大小信息存放在rect中
        size = mPaint.measureText(str);//獲取文本的寬
        canvas.drawText(str + size, 100, 120, mPaint);

        mPaint.setTextSize(30);
        mPaint.getTextBounds(str, 0, str.length(), rect); //測量文本大小,將文本大小信息存放在rect中
        size = mPaint.measureText(str);//獲取文本的寬
        canvas.drawText(str + size, 100, 150, mPaint);

        mPaint.setTextSize(40);
        mPaint.getTextBounds(str, 0, str.length(), rect); //測量文本大小桑包,將文本大小信息存放在rect中
        size = mPaint.measureText(str);//獲取文本的寬
        canvas.drawText(str + size, 100, 190, mPaint);


        mPaint.setTextSize(50);
        mPaint.getTextBounds(str, 0, str.length(), rect); //測量文本大小南蓬,將文本大小信息存放在rect中
        size = mPaint.measureText(str);//獲取文本的寬
        canvas.drawText(str + size, 100, 240, mPaint);

        postInvalidate();
        invalidate();
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市哑了,隨后出現(xiàn)的幾起案子赘方,更是在濱河造成了極大的恐慌,老刑警劉巖弱左,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件窄陡,死亡現(xiàn)場離奇詭異,居然都是意外死亡拆火,警方通過查閱死者的電腦和手機(jī)跳夭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來们镜,“玉大人币叹,你說我怎么就攤上這事∧O粒” “怎么了颈抚?”我有些...
    開封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長嚼鹉。 經(jīng)常有香客問我贩汉,道長驱富,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任匹舞,我火速辦了婚禮褐鸥,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘策菜。我一直安慰自己晶疼,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開白布又憨。 她就那樣靜靜地躺著翠霍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蠢莺。 梳的紋絲不亂的頭發(fā)上寒匙,一...
    開封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音躏将,去河邊找鬼锄弱。 笑死,一個(gè)胖子當(dāng)著我的面吹牛祸憋,可吹牛的內(nèi)容都是我干的会宪。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼蚯窥,長吁一口氣:“原來是場噩夢啊……” “哼掸鹅!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起拦赠,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤巍沙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后荷鼠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體句携,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年允乐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了矮嫉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡牍疏,死狀恐怖蠢笋,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情麸澜,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布奏黑,位于F島的核電站炊邦,受9級(jí)特大地震影響编矾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜馁害,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一窄俏、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧碘菜,春花似錦凹蜈、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至计雌,卻和暖如春悄晃,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背凿滤。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來泰國打工妈橄, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人翁脆。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓眷蚓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親反番。 傳聞我的和親對(duì)象是個(gè)殘疾皇子沙热,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

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