美文网首页Android技术知识Android进阶之路手机移动程序开发
Android关于Paint你所知道的和不知道的一切

Android关于Paint你所知道的和不知道的一切

作者: e4e52c116681 | 来源:发表于2018-11-07 13:03 被阅读12次

    零、前言:

    1.曾经也算半个艺术家,深知笔的重要性与复杂性
    2.Android里的Paint设置项好多基本上都是setXXX,getXXX,很多文字相关的内容都在Paint里
    3.主要由画笔常规配置,画笔类型、画笔特效(线效,着色,滤色)、画笔文字
    4.本文暂时还无法覆盖Paint的所有API,能用的吾尽量都会涉及一下

    最主要的还是set方法
    paint的Set一览.png

    一、画笔的常规配置

    public void setColor(@ColorInt int color) //设置颜色
    public void setAlpha(int a)//设置透明度
    public void setARGB(int a, int r, int g, int b)//设置ARGB颜色
    public void setStrokeWidth(float width)//设置宽度
    public void setAntiAlias(boolean aa)//设置抗锯齿
    
    基本设置.png

    二、笔的样式:Paint.Style.:[#FILL|STROKE|FILL_AND_STROKE]

    /**
     * 样式测试
     * @param canvas
     */
    private void testStyle(Canvas canvas) {
        Rect rect = new Rect(0, 0, 100, 100);
        mRedPaint.setStrokeWidth(15);
        canvas.save();
        
        mRedPaint.setStyle(Paint.Style.FILL);
        canvas.translate(50, 450);
        canvas.drawRect(rect, mRedPaint);
        
        canvas.translate(150, 0);
        mRedPaint.setStyle(Paint.Style.STROKE);
        canvas.drawRect(rect, mRedPaint);
        
        canvas.translate(150 , 0);
        mRedPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        canvas.drawRect(rect, mRedPaint);
        canvas.restore();
        mRedPaint.setStrokeWidth(40);
    }
    
    画笔样式测试.png

    三、线帽:Paint.Cap.:[#BUTT|ROUND|SQUARE]

    1.绘制圆形的点:Paint.Cap.ROUND
    /**
     * 绘制圆形的点
     *
     * @param canvas
     */
    private void drawPos(Canvas canvas) {
        //设置画笔圆帽
        mRedPaint.setStrokeCap(Paint.Cap.ROUND);
        mRedPaint.setStrokeWidth(20);
        //绘制点
        canvas.drawPoint(100, 100, mRedPaint);
        canvas.drawPoints(new float[]{
                400, 400, 500, 500,
                600, 400, 700, 350,
                800, 300, 900, 300
        }, mRedPaint);
    }
    
    绘制圆点.png

    2.三种线帽比较

    /**
     * 线帽型状测试:Paint.Cap.BUTT、Paint.Cap.ROUND、Paint.Cap.SQUARE
     *
     * @param canvas
     */
    private void testOfCap(Canvas canvas) {
        canvas.save();
        canvas.translate(150, 200);
        //线帽测试:
        mRedPaint.setStrokeCap(Paint.Cap.BUTT);//无头(默认)
        canvas.drawLine(0, 0, 0, 200, mRedPaint);
        canvas.translate(50, 0);
        mRedPaint.setStrokeCap(Paint.Cap.ROUND);//圆头
        canvas.drawLine(0, 0, 0, 200, mRedPaint);
        canvas.translate(50, 0);
        mRedPaint.setStrokeCap(Paint.Cap.SQUARE);//方头
        canvas.drawLine(0, 0, 0, 200, mRedPaint);
        canvas.restore();
    }
    
    线帽型状测试.png

    四、线交角测试:Paint.Join.:[#BEVEL|ROUND|MITER]

    注意:只有路径绘制的线才有交角效果

    /**
     * 角型测试:Paint.Join.BEVEL、Paint.Join.ROUND、Paint.Join.MITER
     *
     * @param canvas
     */
    private void testOfJoin(Canvas canvas) {
        mRedPaint.setStyle(Paint.Style.STROKE);
        mRedPaint.setStrokeWidth(40);
        Path path = new Path();
        path.moveTo(30, 0);
        path.lineTo(0, 100);
        path.lineTo(100, 100);
        
        canvas.save();
        canvas.translate(600, 100);
        mRedPaint.setStrokeJoin(Paint.Join.BEVEL);//直线(默认)
        canvas.drawPath(path, mRedPaint);
        
        canvas.translate(150, 0);
        mRedPaint.setStrokeJoin(Paint.Join.ROUND);//圆角
        canvas.drawPath(path, mRedPaint);
        
        canvas.translate(150, 0);
        mRedPaint.setStrokeJoin(Paint.Join.MITER);//锐角
        canvas.drawPath(path, mRedPaint);
        canvas.restore();
    }
    
    线交角测试.png

    五、Paint的路径效果

    1.虚线:DashPathEffect(new float[]{a, b, a1, b1...}, offSet)

    第一参为显隐线段的长度,第二参为偏移值
    下面会动的线是不断改变偏移量:mDashOffSet的结果

    虚线效果.gif
    /**
     * 虚线测试
     *
     * @param canvas
     */
    private void dashEffect(Canvas canvas) {
        mEffectPaint = new Paint(mRedPaint);
        mEffectPaint.setStrokeCap(Paint.Cap.BUTT);
        //显示100,隐藏50,显示50,隐藏50,的循环
        mEffectPaint.setPathEffect(new DashPathEffect(new float[]{100, 50, 50, 50}, 0));
        Path path = new Path();
        path.moveTo(100, 650);
        path.lineTo(1000, 650);
        canvas.drawPath(path, mEffectPaint);
        //显示100,隐藏50,显示60,隐藏50,的循环,偏移:mDashOffSet
        mEffectPaint.setPathEffect(new DashPathEffect(new float[]{100, 50, 50, 50}, mDashOffSet));
        Path pathOffset50 = new Path();
        pathOffset50.moveTo(100, 750);
        pathOffset50.lineTo(1000, 750);
        canvas.drawPath(pathOffset50, mEffectPaint);
    }
    

    2.折角弧:CornerPathEffect(corner)

    动画是不断改变圆角大小:mEffectCorner的结果

    折角弧.gif
    /**
     * 圆角折线
     *
     * @param canvas
     */
    private void cornerEffect(Canvas canvas) {
        mEffectPaint.setPathEffect(new CornerPathEffect(mEffectCorner));
        mEffectPaint.setStyle(Paint.Style.STROKE);
        mEffectPaint.setStrokeWidth(40);
        Path path = new Path();
        path.moveTo(550, 550);
        path.lineTo(900, 300);
        path.lineTo(1000, 550);
        canvas.drawPath(path, mEffectPaint);
        //蓝色辅助线
        Paint tempPaint = new Paint();
        tempPaint.setStyle(Paint.Style.STROKE);
        tempPaint.setColor(Color.BLUE);
        tempPaint.setStrokeWidth(2);
        tempPaint.setPathEffect(new DashPathEffect(new float[]{20, 20}, 0));
        Path helpPath = new Path();
        helpPath.moveTo(550, 550);
        helpPath.lineTo(900, 300);
        helpPath.lineTo(1000, 550);
        canvas.drawPath(helpPath, tempPaint);
    }
    

    3.离散路径:DiscretePathEffect(小段长,偏移量)
    离散路径.png
    /**
     * 离散路径
     *
     * @param canvas
     */
    private void discreteEffect(Canvas canvas) {
        canvas.save();//保存画布状态
        canvas.translate(0, 950);
        //第一个参数:将原来的路径切成多长的线段,越小,所切成的小线段越多
        //第二参数:被切成的每个小线段的可偏移距离。越大,每个线段的可偏移距离就越大。
        Path path = new Path();
        // 定义路径的起点
        path.moveTo(100, 0);
        path.lineTo(600, -100);
        path.lineTo(1000, 0);
        
        mEffectPaint.setPathEffect(new DiscretePathEffect(2, 5));
        mEffectPaint.setStrokeWidth(2);
        canvas.drawPath(path, mEffectPaint);
        canvas.translate(0, 100);
        mEffectPaint.setPathEffect(new DiscretePathEffect(20, 5));
        canvas.drawPath(path, mEffectPaint);
        canvas.restore();//重新储存画布状态
    }
    

    4.路径点样:PathDashPathEffect(路径,间距,偏移,样式)
    路径样点.gif

    通过动图可以很清楚得看出三个样式的区别
    动图是不断改变偏移量:mDashOffSet的结果

    //Path shape:表示[路径点样],这里是一个五角星
    //float advance:表示两个[路径点样]间的距离
    //float phase:路径绘制偏移距离
    //Style style:表示在遇到转角时的过渡样式
    // ----Style.ROTATE表示通过旋转[路径点样]来过渡转角;
    // ----Style.MORPH表示通过变形[路径点样]来过渡转角;
    // ----Style.TRANSLATE表示通过位移[路径点样]来过渡转角。
    
    /**
     * 路径点样路径样式
     *
     * @param canvas
     */
    private void PathDashEffect(Canvas canvas) {
        canvas.save();
        canvas.translate(0, 1100);
        Path path = new Path();
        // 定义路径的起点
        path.moveTo(100, 80);
        path.lineTo(600, -100);
        path.lineTo(1000, 80);
        //变形过渡
        mEffectPaint.setPathEffect(new PathDashPathEffect(
                CommonPath.nStarPath(5, 16, 8), 40, mDashOffSet, PathDashPathEffect.Style.ROTATE));
        canvas.drawPath(path, mEffectPaint);
        canvas.restore();
        //旋转过渡
        canvas.save();
        canvas.translate(0, 1200);
        mEffectPaint.setPathEffect(new PathDashPathEffect(
                CommonPath.nStarPath(5, 16, 8), 40, mDashOffSet, PathDashPathEffect.Style.MORPH));
        canvas.drawPath(path, mEffectPaint);
        canvas.restore();
        //移动过渡
        canvas.save();
        canvas.translate(0, 1300);
        mEffectPaint.setPathEffect(new PathDashPathEffect(
                CommonPath.nStarPath(5, 16, 8), 40, mDashOffSet, PathDashPathEffect.Style.TRANSLATE));
        canvas.drawPath(path, mEffectPaint);
        canvas.restore();
    }
    /**
     * 离散路径
     *
     * @param canvas
     */
    private void discreteEffect(Canvas canvas) {
        canvas.save();//保存画布状态
        canvas.translate(0, 950);
        //第一个参数:将原来的路径切成多长的线段,越小,所切成的小线段越多
        //第二参数:被切成的每个小线段的可偏移距离。越大,每个线段的可偏移距离就越大。
        Path path = new Path();
        // 定义路径的起点
        path.moveTo(100, 0);
        path.lineTo(600, -100);
        path.lineTo(1000, 0);
        mEffectPaint.setPathEffect(new DiscretePathEffect(2, 5));
        mEffectPaint.setStrokeWidth(2);
        canvas.drawPath(path, mEffectPaint);
        canvas.translate(0, 100);
        mEffectPaint.setPathEffect(new DiscretePathEffect(20, 5));
        canvas.drawPath(path, mEffectPaint);
        canvas.restore();//重新储存画布状态
    }
    
    n角星路径封装:
        /**
         * n角星路径
         *
         * @param num 几角星
         * @param R   外接圆半径
         * @param r   内接圆半径
         * @return n角星路径
         */
        public static Path nStarPath(int num, float R, float r) {
            Path path = new Path();
            float perDeg = 360 / num;
            float degA = perDeg / 2 / 2;
            float degB = 360 / (num - 1) / 2 - degA / 2 + degA;
    
            path.moveTo(
                    (float) (Math.cos(rad(degA + perDeg * 0)) * R + R * Math.cos(rad(degA))),
                    (float) (-Math.sin(rad(degA + perDeg * 0)) * R + R));
            for (int i = 0; i < num; i++) {
                path.lineTo(
                        (float) (Math.cos(rad(degA + perDeg * i)) * R + R * Math.cos(rad(degA))),
                        (float) (-Math.sin(rad(degA + perDeg * i)) * R + R));
                path.lineTo(
                        (float) (Math.cos(rad(degB + perDeg * i)) * r + R * Math.cos(rad(degA))),
                        (float) (-Math.sin(rad(degB + perDeg * i)) * r + R));
            }
            path.close();
            return path;
        }
    
        /**
         * 角度制化为弧度制
         *
         * @param deg 角度
         * @return 弧度
         */
        public static float rad(float deg) {
            return (float) (deg * Math.PI / 180);
        }
    

    5.叠加特效:PathDashPathEffect(e1,e2...)(此处演示:离散效果+样点效果)
    特效叠加.gif
    /**
     * 叠加样式
     *
     * @param canvas
     */
    private void composeEffect(Canvas canvas) {
        mEffectPaint.setStyle(Paint.Style.STROKE);
        mEffectPaint.setStrokeWidth(40);
        canvas.save();
        canvas.translate(0, 1400);
        Path path = new Path();
        // 定义路径的起点
        path.moveTo(100, 80);
        path.lineTo(600, -100);
        path.lineTo(1000, 80);
        PathDashPathEffect effect1 = new PathDashPathEffect(
                CommonPath.nStarPath(5, 16, 8), 40, mDashOffSet, PathDashPathEffect.Style.ROTATE);
        DiscretePathEffect effect2 = new DiscretePathEffect(20, 5);
        mEffectPaint.setPathEffect(new ComposePathEffect(effect1, effect2));//离散效果+样点效果
        canvas.drawPath(path, mEffectPaint);
        canvas.restore();
    }
    

    6.路径叠加
    路径叠加.gif
    /**
     * 路径叠加
     *
     * @param canvas
     */
    private void sumEffect(Canvas canvas) {
        canvas.save();
        canvas.translate(0, 1500);
        Path path = new Path();
        // 定义路径的起点
        path.moveTo(100, 80);
        path.lineTo(600, -100);
        path.lineTo(1000, 80);
        PathDashPathEffect effect1 = new PathDashPathEffect(
                CommonPath.nStarPath(5, 16, 8), 40, mDashOffSet, PathDashPathEffect.Style.ROTATE);
        DiscretePathEffect effect2 = new DiscretePathEffect(20, 5);
        mEffectPaint.setPathEffect(new SumPathEffect(effect1, effect2));//离散效果+样点效果
        canvas.drawPath(path, mEffectPaint);
        canvas.restore();
    }
    

    六.着色器:Shader

    一个很简单的类,有5个子类:

    Shader.png
    1.线性渐变:
    1).new LinearGradient(渐变起点x,y,渐变终点x,y,渐变色1,渐变色2,渐变模式)

    渐变模式:Shader.TileMode.[MIRROR|CLAMP|REPEAT] (图中很形象,就不解释了)

            int colorStart = Color.parseColor("#84F125");
            int colorEnd = Color.parseColor("#5825F1");
            canvas.save();
            canvas.translate(mCoo.x, mCoo.y);
            mRedPaint.setStyle(Paint.Style.FILL);
            mRedPaint.setShader(
                    new LinearGradient(
                            -200, 0, 200, 0,
                            colorStart, colorEnd,
                            Shader.TileMode.MIRROR
    
                    ));
            canvas.drawRect(-400,-200,400,-100,mRedPaint);
    
            canvas.translate(0, 150);
            mRedPaint.setShader(
                    new LinearGradient(
                            -100, 0, 100, 0,
                            colorStart, colorEnd,
                            Shader.TileMode.CLAMP
                    ));
            canvas.drawRect(-400,-200,400,-100,mRedPaint);
    
            canvas.translate(0, 150);
            mRedPaint.setShader(
                    new LinearGradient(
                            -100, 0, 100, 0,
                            colorStart, colorEnd,
                            Shader.TileMode.REPEAT
                    ));
            canvas.drawRect(-400,-200,400,-100,mRedPaint);
    
    线性渐变.png
    2).多色多点渐变:LinearGradient(渐变起点x,y,渐变终点x,y,颜色数组,位置百分点数组0~1,渐变模式)
    多色渐变.png
    int[] colors = new int[]{
            Color.parseColor("#F60C0C"),//红
            Color.parseColor("#F3B913"),//橙
            Color.parseColor("#E7F716"),//黄
            Color.parseColor("#3DF30B"),//绿
            Color.parseColor("#0DF6EF"),//青
            Color.parseColor("#0829FB"),//蓝
            Color.parseColor("#B709F4"),//紫
    };
    float[] pos = new float[]{
            1.f / 7, 2.f / 7, 3.f / 7, 4.f / 7, 5.f / 7, 6.f / 7, 1
    };
    
    canvas.translate(0, 150);
    mRedPaint.setShader(
            new LinearGradient(
                    -300, 0, 300, 0,
                    colors, pos,
                    Shader.TileMode.CLAMP
    
            ));
    canvas.drawRect(-400, -200, 400, -100, mRedPaint);
    

    2.径向渐变:RadialGradient
    1).两色渐变:RadialGradient(渐变中心,渐变半径,颜色1,颜色2,渐变模式)
    canvas.translate(mCoo.x, mCoo.y);
    int colorStart = Color.parseColor("#84F125");
    int colorEnd = Color.parseColor("#5825F1");
    mRedPaint.setStyle(Paint.Style.FILL);
    mRedPaint.setShader(
            new RadialGradient(
                   0,0,50,
                    colorStart, colorEnd,
                    Shader.TileMode.MIRROR
    
            ));
    
    canvas.drawCircle(0, 0, 150, mRedPaint);
    
    canvas.translate(350, 0);
    mRedPaint.setShader(
            new RadialGradient(
                    0,0,50,
                    colorStart, colorEnd,
                    Shader.TileMode.CLAMP
    
            ));
    canvas.drawCircle(0, 0, 150, mRedPaint);
    
    
    canvas.translate(350, 0);
    mRedPaint.setShader(
            new RadialGradient(
                    0,0,50,
                    colorStart, colorEnd,
                    Shader.TileMode.REPEAT
    
            ));
    canvas.drawCircle(0, 0, 150, mRedPaint);
    
    径像渐变.png
    2).多色多点径向渐变:

    RadialGradient(渐变中心,渐变半径,渐变模式,颜色数组,位置百分点数组0~1,渐变模式)

    多色径向渐变.png
    int[] colors = new int[]{
            Color.parseColor("#F60C0C"),//红
            Color.parseColor("#F3B913"),//橙
            Color.parseColor("#E7F716"),//黄
            Color.parseColor("#3DF30B"),//绿
            Color.parseColor("#0DF6EF"),//青
            Color.parseColor("#0829FB"),//蓝
            Color.parseColor("#B709F4"),//紫
    };
    float[] pos = new float[]{
            1.f / 7, 2.f / 7, 3.f / 7, 4.f / 7, 5.f / 7, 6.f / 7, 1
    };
    mRedPaint.setStyle(Paint.Style.FILL);
    mRedPaint.setShader(
            new RadialGradient(
                    0, 0, 200,
                    colors, pos,
                    Shader.TileMode.CLAMP
            ));
    canvas.drawCircle(0, 0, 250, mRedPaint);
    
    3.扫描渐变:SweepGradient

    这个要比上面的简单一点,没有渐变的模式
    双色扫描渐变:SweepGradient(中心点x,y,颜色1,颜色2)
    多色扫描渐变:SweepGradient(中心点x,y,颜色数组,位置百分点数组0~1)

    扫描渐变.png
    int colorStart = Color.parseColor("#84F125");
    int colorEnd = Color.parseColor("#5825F1");
    mRedPaint.setStyle(Paint.Style.FILL);
    mRedPaint.setShader(
            new SweepGradient(0, 0, colorStart, colorEnd));
    canvas.drawCircle(0, 0, 150, mRedPaint);
    
    canvas.translate(400, 0);
    int[] colors = new int[]{
            Color.parseColor("#F60C0C"),//红
            Color.parseColor("#F3B913"),//橙
            Color.parseColor("#E7F716"),//黄
            Color.parseColor("#3DF30B"),//绿
            Color.parseColor("#0DF6EF"),//青
            Color.parseColor("#0829FB"),//蓝
            Color.parseColor("#B709F4"),//紫
    };
    float[] pos = new float[]{
            1.f / 7, 2.f / 7, 3.f / 7, 4.f / 7, 5.f / 7, 6.f / 7, 1
    };
    mRedPaint.setShader(
            new SweepGradient(0, 0, colors, pos));
    canvas.drawCircle(0, 0, 150, mRedPaint);
    
    4.图片着色器:BitmapShader(图片,着色模式x,着色模式y)

    用图片的所有像素点作为画笔的颜色

    1).文字的图片底色:
    //加载图片,生成图片着色器
    Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.menu_bg);
    BitmapShader bs = new BitmapShader(bitmap, Shader.TileMode.CLAMP,Shader.TileMode.CLAMP);
    mRedPaint.setShader(bs);
    mRedPaint.setTextSize(150);
    mRedPaint.setStrokeWidth(10);
    mRedPaint.setStyle(Paint.Style.FILL_AND_STROKE);
    canvas.drawText("张风捷特烈", 0, 500, mRedPaint);
    
    图片着色.png
    2)路径+图片着色器实现裁剪图片:路径Path相关知识见上一篇:
    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.menu_bg);
    BitmapShader bs = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
    mRedPaint.setShader(bs);
    
    mRedPaint.setStyle(Paint.Style.FILL);
    Path path = CommonPath.nStarPath(8, 500, 250);
    canvas.drawPath(path, mRedPaint);
    
    使用路径裁剪图片.png

    还有一个ComposeShader比较复杂,以后有需求会专门写一篇


    七、颜色过滤器:(具体原理是颜色运算,这里全当玩玩看看吧,暂不深究)

    ColorFilter只有三个子类
    颜色过滤器.png
    1.LightingColorFilter(颜色1,颜色2):

    看图体会一下吧...我不说了

    LightingColorFilter测试.png
            Bitmap mainBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.menu_bg);
            mRedPaint.setStyle(Paint.Style.FILL);
            mRedPaint.setColorFilter(new LightingColorFilter(
                    Color.parseColor("#FF0000"),//红
                    Color.parseColor("#0000ff")//蓝
            ));
            canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
    
            canvas.translate(350, 0);
            mRedPaint.setColorFilter(new LightingColorFilter(
                    Color.parseColor("#FF0000"),//红
                    Color.parseColor("#00ff00")//绿
            ));
            canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
    
            canvas.translate(350, 0);
            mRedPaint.setColorFilter(new LightingColorFilter(
                    Color.parseColor("#FF0000"),//红
                    Color.parseColor("#000000")//黑
            ));
            canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
            canvas.restore();
    
    2.PorterDuffColorFilter(颜色,模式--PorterDuff.Mode):

    PorterDuff.Mode一共17中,在Color专题会详述,这里举几个栗子看看

    PorterDuffColorFilter测试.png
    Bitmap mainBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.menu_bg);
    mRedPaint.setStyle(Paint.Style.FILL);
    
    mRedPaint.setColorFilter(new PorterDuffColorFilter(
            Color.parseColor("#0000ff"), PorterDuff.Mode.DARKEN));
    canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
    
    canvas.translate(350, 0);
    mRedPaint.setColorFilter(new PorterDuffColorFilter(
            Color.parseColor("#0000ff"),PorterDuff.Mode.LIGHTEN
    ));
    canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
    
    canvas.translate(350, 0);
    mRedPaint.setColorFilter(new PorterDuffColorFilter(
            Color.parseColor("#0000ff"),PorterDuff.Mode.SCREEN
    ));
    canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
    
    canvas.translate(350, 0);
    mRedPaint.setColorFilter(new PorterDuffColorFilter(
            Color.parseColor("#0000ff"),PorterDuff.Mode.OVERLAY
    ));
    canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
    
    3.ColorMatrixColorFilter(颜色变换矩阵或25个float数)

    刚好前端时间对ColorMatrix有一点研究,这里拿来用用

    颜色矩阵.png ColorMatrix.png
            Bitmap mainBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.menu_bg);
            mRedPaint.setStyle(Paint.Style.FILL);
    
            //关闭RGB颜色通道(变为黑色),后偏移红色255
            float[] matrix = new float[]{
                    -1, 0, 0, 0, 255,
                    0, -1, 0, 0, 0,
                    0, 0, -1, 0, 0,
                    0, 0, 0, 1, 0
            };
            ColorMatrix colorMatrix = new ColorMatrix(matrix);
            mRedPaint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
            canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
    
    
            canvas.translate(350, 0);
            //关闭RGB颜色通道(变为黑色),后偏移蓝色255
            float[] matrix2 = new float[]{
                    -1, 0, 0, 0, 0,
                    0, -1, 0, 0, 0,
                    0, 0, -1, 0, 255,
                    0, 0, 0, 1, 0
            };
            ColorMatrix colorMatrix2 = new ColorMatrix(matrix2);
            mRedPaint.setColorFilter(new ColorMatrixColorFilter(colorMatrix2));
            canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
    
            canvas.translate(350, 0);
            //关闭RGB颜色通道(变为黑色),后偏移三色255
            float[] matrix3 = new float[]{
                    -1, 0, 0, 0, 255,
                    0, -1, 0, 0, 255,
                    0, 0, -1, 0, 255,
                    0, 0, 0, 1, 0
            };
            ColorMatrix colorMatrix3 = new ColorMatrix(matrix3);
            mRedPaint.setColorFilter(new ColorMatrixColorFilter(colorMatrix3));
            canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
    
            canvas.translate(350, 0);
    
            float[] matrix4 = new float[]{
                    //只要把RGB三通道的色彩信息设置成一样:即:R=G=B,
                    // 为了保证图像亮度不变,同一个通道中的R+G+B=1
                    0.3086f, 0.6094f, 0.0820f, 0, 0,
                    0.3086f, 0.6094f, 0.0820f, 0, 0,
                    0.3086f, 0.6094f, 0.0820f, 0, 0,
                    0, 0, 0, 1, 0
            };
            ColorMatrix colorMatrix4 = new ColorMatrix(matrix4);
            mRedPaint.setColorFilter(new ColorMatrixColorFilter(colorMatrix4));
            canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
    

    七、文字相关

    字体.setTypeface(Typeface.SANS_SERIF);
    对齐方式.setTextAlign(Paint.Align.LEFT);
    字体大小.setTextSize(100);
    
    1.对齐方式与内置字体:

    对齐:Paint.Align.[#LEFT|RIGHT|CENTER]
    内置字体:Typeface.[#DEFAULT|DEFAULT_BOLD|SANS_SERIF|SERIF|MONOSPACE]

    canvas.save();
    canvas.translate(550, 1600);
    mTextPaint.setTypeface(Typeface.SANS_SERIF);
    mTextPaint.setTextAlign(Paint.Align.LEFT);
    mTextPaint.setTextSize(100);
    canvas.drawText("SANS_SERIF", 0, 0, mTextPaint);
    Paint tempPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    tempPaint.setStrokeWidth(4);
    tempPaint.setColor(Color.RED);
    tempPaint.setStyle(Paint.Style.STROKE);
    canvas.drawRect(0, - 100, mWinSize.x, 0, tempPaint);
    
    canvas.translate(0, 150);
    mTextPaint.setTextAlign(Paint.Align.RIGHT);
    mTextPaint.setTypeface(Typeface.SERIF);
    canvas.drawText("SERIF", 0, 0, mTextPaint);
    canvas.drawRect(0, - 100, mWinSize.x, 0, tempPaint);
    
    canvas.translate(0, 150);
    mTextPaint.setTypeface(Typeface.MONOSPACE);
    mTextPaint.setTextAlign(Paint.Align.CENTER);
    canvas.drawText("MONOSPACE", 0, 0, mTextPaint);
    canvas.drawRect(0, - 100, mWinSize.x, 0, tempPaint);
    
    canvas.restore();
    
    文字相关.png
    2.创建字体:外部字体放在assets目录下
    /**
     * 创建字体
     * @param canvas
     */
    private void createTypeface(Canvas canvas) {
        mTextPaint.setTextSize(50);
        canvas.save();
        canvas.translate(50, 1600);
        mTextPaint.setTypeface(Typeface.MONOSPACE);
        canvas.drawText("MONOSPACE", 0, 0, mTextPaint);
        //粗体
        canvas.translate(0, 100);
        Typeface typeface = Typeface.create(Typeface.MONOSPACE, Typeface.BOLD);
        mTextPaint.setTypeface(typeface);
        canvas.drawText("MONOSPACE+BOLD", 0, 0, mTextPaint);
        //斜体
        canvas.translate(0, 100);
        Typeface typeface2 = Typeface.create(Typeface.MONOSPACE, Typeface.ITALIC);
        mTextPaint.setTypeface(typeface2);
        canvas.drawText("MONOSPACE+ITALIC", 0, 0, mTextPaint);
        //粗斜体
        canvas.translate(0, 100);
        Typeface typeface3 = Typeface.create(Typeface.MONOSPACE, Typeface.BOLD_ITALIC);
        mTextPaint.setTypeface(typeface3);
        canvas.drawText("MONOSPACE+BOLD_ITALIC", 0, 0, mTextPaint);
        //使用外部字体
        canvas.translate(0, 100);
        Typeface myFont = Typeface.createFromAsset(getContext().getAssets(), "ACHAFSEX.TTF");
        mTextPaint.setTypeface(myFont);
        canvas.drawText("Hello I am Toly", 0, 0, mTextPaint);
        canvas.restore();
    }
    
    创建字体.png
    3.文字的测量:FontMetrics
    1).字体测量类:FontMetrics
        public static class FontMetrics {
            public float   top;//最顶
            public float   ascent;//
            public float   leading;
            public float   descent;
            public float   bottom;//最底
        }
    
    2).SERIF字体测试:(试了一下不同字体这几个属性都不同的,有的字体相差很大)
    字体5线.png
        /**
         * 获取字体尺寸信息
         * @param canvas
         */
        private void fontMetricsTest(Canvas canvas) {
            canvas.save();
            canvas.translate(100, 500);
            mTextPaint.setTextSize(200);
            mTextPaint.setTypeface(Typeface.SERIF);
            canvas.drawText("I am Toly", 0, 0, mTextPaint);
            //获取字体尺寸
            Paint.FontMetrics fm = mTextPaint.getFontMetrics();
    
            Log.e(TAG, "top: " + fm.top);
            Log.e(TAG, "ascent: " + fm.ascent);
            Log.e(TAG, "leading: " + fm.leading);
            Log.e(TAG, "descent: " + fm.descent);
            Log.e(TAG, "bottom: " + fm.bottom);
    
            Paint tempPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            tempPaint.setStrokeWidth(1);
            tempPaint.setColor(Color.RED);
            tempPaint.setStyle(Paint.Style.STROKE);
    
            canvas.drawLine(0, fm.top, mWinSize.x, fm.top, tempPaint);
    
            tempPaint.setColor(Color.MAGENTA);
            canvas.drawLine(0, fm.ascent, mWinSize.x, fm.ascent, tempPaint);
    
            tempPaint.setColor(Color.parseColor("#4C17F9"));
            canvas.drawLine(0, fm.leading, mWinSize.x, fm.leading, tempPaint);
    
            tempPaint.setColor(Color.GREEN);
            canvas.drawLine(0, fm.descent, mWinSize.x, fm.descent, tempPaint);
    
            tempPaint.setColor(Color.parseColor("#E74EDD"));
            canvas.drawLine(0, fm.bottom, mWinSize.x, fm.bottom, tempPaint);
    
            canvas.restore();
        }
    
    
    2018-11-05 21:17:35.264 28726-28726/? E/PaintView: top: -209.57031
    2018-11-05 21:17:35.264 28726-28726/? E/PaintView: ascent: -185.54688
    2018-11-05 21:17:35.264 28726-28726/? E/PaintView: leading: 0.0
    2018-11-05 21:17:35.264 28726-28726/? E/PaintView: descent: 48.828125
    2018-11-05 21:17:35.264 28726-28726/? E/PaintView: bottom: 50.0
    

    3).获取文字矩形区
    String text = "I am Toly";
    Rect textRect = new Rect();
    mTextPaint.getTextBounds(text, 0, text.length(), textRect);
    Log.e(TAG, textRect.toShortString());// [7,-152][886,49]
    //绘制矩形
    tempPaint.setColor(Color.parseColor("#66F4F628"));
    tempPaint.setStyle(Paint.Style.FILL);
    canvas.drawRect(textRect, tempPaint);
    
    文字最小矩形区.png
    4).文字的变形操作
    mTextPaint.setTextScaleX(.5f);//水平伸缩
    mTextPaint.setStrikeThruText(true);//删除线
    mTextPaint.setUnderlineText(true);//下划线
    mTextPaint.setTextSkewX(-.5f);//倾斜
    
    其他效果.png

    就先这样吧,还有很多不常用的,以后有需求遇到了,在加吧

    后记:捷文规范

    1.本文成长记录及勘误表
    项目源码 日期 备注
    V0.1--无 2018-11-7 Android关于Paint你所知道的和不知道的一切
    2.更多关于我
    笔名 QQ 微信 爱好
    张风捷特烈 1981462002 zdl1994328 语言
    我的github 我的简书 我的CSDN 个人网站
    3.声明

    1----本文由张风捷特烈原创,转载请注明
    2----欢迎广大编程爱好者共同交流
    3----个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正
    4----看到这里,我在此感谢你的喜欢与支持


    icon_wx_200.png

    相关文章

      网友评论

        本文标题:Android关于Paint你所知道的和不知道的一切

        本文链接:https://www.haomeiwen.com/subject/jrtvxqtx.html