UI绘制(四)——Paint高级应用

线帽

Paint.setStrokeCap(Paint.Cap.BUTT); 无线帽
Paint.setStrokeCap(Paint.Cap.ROUND); 圆形线帽
Paint.setStrokeCap(Paint.Cap.SQUARE);方形线帽

f18e0eb1379575428eefcd82d1216005.png

拐角风格

Paint.setStrokeJoin(Paint.Join.MITER); 默认
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):渐变起始点坐标
         * (x1,y1):渐变结束点坐标
         * color0:渐变开始点颜色,16进制的颜色表示,必须要带有透明度
         * color1:渐变结束颜色
         * colors:渐变数组
         * positions:位置数组,position的取值范围[0,1],作用是指定某个位置的颜色值,如果传null,渐变就线性变化。
         * tile:用于指定控件区域大于指定的渐变区域时,空白区域的颜色填充方法
         */
        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);
环形渲染
         /**
         * 环形渲染,RadialGradient(float centerX, float centerY, float radius, @ColorInt int colors[], @Nullable float stops[], TileMode tileMode)
         * centerX ,centerY:shader的中心坐标,开始渐变的坐标
         * radius:渐变的半径
         * centerColor,edgeColor:中心点渐变颜色,边界的渐变颜色
         * colors:渐变颜色数组
         * stoops:渐变位置数组,类似扫描渐变的positions数组,取值[0,1],中心点为0,半径到达位置为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 渐变中心坐标
         * color0,color1:渐变开始结束颜色
         * colors,positions:类似LinearGradient,用于多颜色渐变,positions为null时,根据颜色线性渐变
         */
        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:构造shader使用的bitmap
         * tileX:X轴方向的TileMode
         * tileY:Y轴方向的TileMode
            REPEAT, 绘制区域超过渲染区域的部分,重复排版
            CLAMP, 绘制区域超过渲染区域的部分,会以最后一个像素拉伸排版
            MIRROR, 绘制区域超过渲染区域的部分,镜像翻转排版
         */
        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表示目标图的Alpha通道;Dc全称为Destination color表示目标图的颜色,[...,..]前半部分计算的是结果图像的Alpha通道值,“,”后半部分计算的是结果图像的颜色值。
    //效果作用于src源图像区域
    public static final PorterDuffXfermode[] sModes = {
            //所绘制不会提交到画布上
            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),

            //取两图层全部区域,交集部分颜色加深
            new PorterDuffXfermode(PorterDuff.Mode.DARKEN),
            //取两图层全部区域,交集部分颜色点亮
            new PorterDuffXfermode(PorterDuff.Mode.LIGHTEN),
            //取两图层交集部分,颜色叠加
            new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY),
            //取两图层全部区域,交集部分滤色
            new PorterDuffXfermode(PorterDuff.Mode.SCREEN),

            //取两图层全部区域,交集部分饱和度相加
            new PorterDuffXfermode(PorterDuff.Mode.ADD),
            //取两图层全部区域,交集部分叠加
            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);

        //蓝色去除掉
        sc = canvas.saveLayer(W, 0, W*2, H, null);
        canvas.translate(W, 0);
        canvas.drawText("蓝色去除掉", 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("颜色亮度调节-绿色", 100,50,labelP);
        ColorMatrix cm1 = new ColorMatrix();
//        //颜色亮度调节-绿色
        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("饱和度调节", 100,50,labelP);
        ColorMatrix cm2 = new ColorMatrix();
//        //饱和度调节0-无色彩, 1- 默认效果, >1饱和度加强
        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("色调调节", 100,50,labelP);
        ColorMatrix cm3 = new ColorMatrix();
        //色调调节-红色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("内外模糊", 100,50,labelP);
        mPaint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.NORMAL));//设置画笔遮罩滤镜 ,传入度数和样式
        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("外模糊内填充", 100,50,labelP);
        mPaint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.SOLID));//设置画笔遮罩滤镜 ,传入度数和样式
        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));//设置画笔遮罩滤镜 ,传入度数和样式
        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("内模糊", 100,50,labelP);
        mPaint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.INNER));//设置画笔遮罩滤镜 ,传入度数和样式
        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);
        // 设置画笔遮罩滤镜 ,传入度数和样式
        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();
    }

你可能感兴趣的:(UI绘制(四)——Paint高级应用)