首页 > 代码库 > Paint基本用法

Paint基本用法

这篇只要记录Paint(画笔)一些基本用法setARGB(设置画笔颜色和透明度)

setARGB(设置画笔颜色和透明度)

paint.setARGB(88,255,0,0);

setARGB(int a, int r, int g, int b)取值都是0~255

setAlpha (int a)设置画笔透明度,取值0~255

setColor(int color) 设置画笔颜色

setAntiAlias(设置抗锯齿)

setAntiAlias(boolean aa) 设置抗锯齿,如果不设置,加载位图的时候可能会出现锯齿状的边界,如果设置,边界就会变的稍微有点模糊,锯齿就看不到了。


setDither(防抖动)

setDither(boolean dither):防抖动,这个属性的需求场景主要出现在绘制渐变色彩或含渐变的图片时,android对不含alpha通道的图片会进行一个转化,

成为RGB565 格式的,这种格式占用内存小,但因为如此,就会出现讨厌的“色带”情景,让人感觉过渡的不是那么柔和,针对这个问题,android提出了

防抖动,它会将原始颜色的过渡处根据两边的色值进行一些改变,从而让颜色过渡更加的柔和,让人觉得是平滑的过渡;

setStyle(画笔样式)

setStyle(Paint.Style style):设置画笔的样式,为FILL,FILL_OR_STROKE,或STROKE;

setStrokeCap(设置画笔帽)

setStrokeCap(Paint.Cap cap):当画笔样式为STROKE或FILL_OR_STROKE时,设置笔刷的图形样式,如圆形样式;
Cap.ROUND,或方形样式Cap.SQUARE

private void setStrokeCap(Canvas canvas) {
        canvas.save();
        paint.setStrokeWidth(50);
        paint.setColor(Color.BLACK);
        paint.setTextSize(40);
        canvas.drawText("没用StrokeCap", 550,40,paint);
        canvas.drawLine(40,20,500,20,paint);
        canvas.restore();

        canvas.save();
        canvas.translate(0,100);
        paint.setStrokeWidth(50);
        paint.setColor(Color.BLACK);
        canvas.drawText("Paint.Cap.ROUND", 550,40,paint);
        paint.setStrokeCap(Paint.Cap.ROUND);
        canvas.drawLine(40,20,500,20,paint);
        canvas.restore();

        canvas.save();
        canvas.translate(0,200);
        paint.setStrokeWidth(50);
        paint.setColor(Color.BLACK);
        canvas.drawText("Paint.Cap.SQUARE", 550,40,paint);
        paint.setStrokeCap(Paint.Cap.SQUARE);
        canvas.drawLine(40,20,500,20,paint);
        canvas.restore();

        canvas.save();
        canvas.translate(0,300);
        paint.setStrokeWidth(50);
        paint.setColor(Color.BLACK);
        canvas.drawText("Paint.Cap.BUTT", 550,40,paint);
        paint.setStrokeCap(Paint.Cap.BUTT);
        canvas.drawLine(40,20,500,20,paint);
        canvas.restore();
    }
技术分享

setSrokeJoin

setSrokeJoin(Paint.Join join):设置绘制时各图形的结合方式,如平滑效果等;

setStrokeWidth(设置画笔粗细度)

setStrokeWidth(float width):当画笔样式为STROKE或FILL_OR_STROKE时,设置笔刷的粗细度;

setXfermode

setXfermode(Xfermode xfermode):设置图形重叠时的处理方式,如合并,取交集或并集;

setShadowLayer(设置阴影层)

setShadowLayer(float radius ,float dx,float dy,int color):在图形下面设置阴影层,产生阴影效果,radius为阴影的角度,dx和dy为阴影在x轴和y轴上的距离,color为阴影的颜色;


Text文本绘制相关:

setFakeBoldText

setFakeBoldText(boolean fakeBoldText):模拟实现粗体文字,设置在小字体上效果会非常差;

setSubpixelText

setSubpixelText(boolean subpixelText):设置该项为true,它可以保证在绘制斜线的时候使用抗锯齿效果来平滑该斜线的外观;

setTextAlign(文字对齐方式)

setTextAlign(Paint.Align align):设置绘制文字的对齐方向;

setTextScaleX(文字伸缩效果)

setTextScaleX(float scaleX):设置绘制文字x轴的缩放比例,可以实现文字的拉伸的效果;

setTextSize(文字字体大小)

setTextSize(float textSize):设置绘制文字的字号大小;

setTextSkewX(文字倾斜度)

setTextSkewX(float skewX):设置斜体文字,skewX为倾斜弧度;

setTypeface(设置自定义字体)

setTypeface(Typeface typeface):设置Typeface对象,即字体风格,包括粗体,斜体以及衬线体,非衬线体等;

Typeface shift = Typeface.createFromAsset(getAssets(), "fonts/Shift.ttf");  
    paint.setTypeface(shift);  


setUnderlineText(文字是否带下划线)

setUnderlineText(boolean underlineText):设置带有下划线的文字效果;

setStrikeThruText(文字是否有删除线效果)

setStrikeThruText(boolean strikeThruText):设置带有删除线的效果;

setColorFilter(画笔颜色过滤器)

setColorFilter(ColorFilter filter)
设置画笔颜色过滤器,可以在绘制颜色时实现不用颜色的变换效果,ColorFilter的子类有ColorMatrixColorFilter,LightingColorFilter,PorterDuffColorFilter

ColorMatrixColorFilter翻译为颜色矩阵过滤器,其用法

public ColorMatrixColorFilter(float[] array)    array为4*5矩阵排列形式

public void setColorFilter(Canvas canvas) {
        paint.setColor(Color.argb(255, 255, 128, 102));
        ColorMatrixColorFilter colorFilter = new ColorMatrixColorFilter(new float[]{
                1, 0, 0, 0, 0,
                0, 1, 0, 0, 0,
                0, 0, 1, 0, 0,
                0, 0, 0, 1, 0
        });
        paint.setColorFilter(colorFilter);
        //画一个圆形
        canvas.drawCircle(200,
                200, 100, paint);
    }

首先创建了一个ColorMatrixColorFilter对象,并且传递进去一个float型的4*5排列的数组,然后调用Paint的setColorFilter方法将ColorMatrixColorFilter对象传入,运行在手机上发现什么变化都没有

其实一个4*5的float数组中分别对应的是RGBA的向量值,第一行代表的是R(红色)的向量值,第二行代表G(绿色)的向量值,第三行代表B(蓝色)的向量值,第四行代表A(透明度)的向量值,这4行分别代表不同的RGBA的向量值,并且值的取值范围是[0.0F , 2.0F],当值为1.0F的时候,表示保持原有的色彩,不发生色彩便宜。so,如果我们想要将上面的红色的圈圈颜色变掉,就不能像上面的代码一样,将所有的向量值都设置为1.0F,修改一个:

public void setColorFilter(Canvas canvas) {
        paint.setColor(Color.argb(255, 255, 128, 102));
        ColorMatrixColorFilter colorFilter = new ColorMatrixColorFilter(new float[]{
                0.5F, 0, 0, 0, 0,
                0, 0.5F, 0, 0, 0,
                0, 0, 0.5F, 0, 0,
                0, 0, 0, 1, 0
        });
        paint.setColorFilter(colorFilter);
        //画一个圆形
        canvas.drawCircle(200,
                200, 100, paint);
    }
自个运行对比一下,效果图就不给出来了

看起来神奇很多。那么,这个色彩矩阵以及这个float数组是怎样做到的呢?或者说是怎样通过计算后得到另外一个色彩值的呢?下面作图来说明一下,我们顶一个ColorMatrix的4*5的float型数组,然后定义一个我们自己MyColor,分别代表RGBA的值:

技术分享

实际上,安卓系统计算色彩值是用矩阵相乘的方式得出的,如上图的样子。这里的MyColor的各项值都要转换到[0,1]之间的值,下面就是我们实际转换的计算方式和结果了。

技术分享

通过上面的计算,我们得到了最终的RGBA的值是(0.5,0.25,0.2,1),说明RGB色彩值都发生了偏移,只有A未偏移,然后我们将这些值乘以255后还原一下看看,是不是跟上图的圈圈的色彩值是一致的呢,好吧,别看了,肯定必须一定是一样的。那么了解色彩矩阵有什么用呢?上面简单的更换一下色彩值而已,Paint类下也提供了setColor()方法,直接将色彩值设置上去,都TMD的方便,还搞什么玩意的矩阵,显得自己牛逼+蛋疼是不是?解释一下,上面的例子不过是个例子而已啊,真正开发的时候肯定是setColor比较简便嘛。问题来了,我们有可能处理的不是一个纯色彩的东西,而是一直图片呢?一张图片是有几十万中色彩值的,这时候setColor()就不可能让他们变色了吧,还是得用色彩矩阵来搞这玩意。下面我们从drawable目录下加载一张图片吧!

 private void drawBitmap(Canvas canvas) {
        //获取图片
        Bitmap mBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.fj_img);
        canvas.drawBitmap(mBitmap, 50, 50, paint);
    }
技术分享
上面的Paint没有做任何的处理,下面我们为Paint设置色彩过滤器吧!

private void drawBitmap(Canvas canvas) {
        ColorMatrixColorFilter colorFilter = new ColorMatrixColorFilter(new float[]{
                0.33F, 0.59F, 0.11F, 0, 0,
                0.33F, 0.59F, 0.11F, 0, 0,
                0.33F, 0.59F, 0.11F, 0, 0,
                0, 0, 0, 1, 0,
        });
        paint.setColorFilter(colorFilter);
        //获取图片
        Bitmap mBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.fj_img);
        canvas.drawBitmap(mBitmap, 50, 50, paint);
    }
技术分享

图片变成黑白的了


LightingColorFilter顾名思义就是“光照色彩过滤器”,就是模拟一个光照照过图像所产生的效果

public LightingColorFilter(int mul, int add)

查看一下Google文档,是这样介绍滴:

光照色彩滤光片,可以用来模拟简单的照明效果。一个lightingcolorfilter定义了两个参数,一个用于与源颜色相乘(称为colormultiply)和一个用于添加到源颜色(称为coloradd)。alpha通道是原封不动的彩色滤光片。给定一个源颜色的RGB,由此产生的特定颜色计算如下:

R‘ = R * colorMultiply.R + colorAdd.R
G‘ = G * colorMultiply.G + colorAdd.G
B‘ = B * colorMultiply.B + colorAdd.B
每个通道值的结果范围是0~255。

上面的介绍写的比较明白,算法也很简单,我们以上面的原图为例,看见蓝天了吗,我们现在去掉这个蓝色的天。根据这个短发描述呢,我们仅仅去掉蓝色,就要将蓝色的通道值改变,将B计算为其它值,这时候colorMultiply.B = 00,colorAdd.B =00,计算得到的B = 00,其它的通道R和G均不变,那么,colorAdd.R=0,colorAdd.G =0;colorMultiply.R = FF,colorMultiply.G =FF,Alpha通道A是忽略的,所以随便设置什么都不会有变化的。

private void setLightingColorFilter(Canvas canvas) {
        LightingColorFilter colorFilter = new LightingColorFilter(0xFFFFFF00, 0x00000000);
        paint.setColorFilter(colorFilter);
        //获取图片
        Bitmap mBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.fj_img);
        canvas.drawBitmap(mBitmap, 50, 50, paint);
    }
技术分享


PorterDuff混合模式的色彩过滤器

public PorterDuffColorFilter(int color, PorterDuff.Mode mode)

Google文档:PorterDuff滤光器可以用于点源像素使用一个单一的颜色和一个特定的波特达夫复合模式。

PorterDuffColorFilter的构造器也很简单,其中第一个参数表示一个16进制的色彩值,第二个参数是一个枚举值PorterDuff.Mode,表示图片混排的模式,PorterDuff.Mode在Android下一共有16种。下面我们先写一个小例子看一下,这里我们还是使用上面的图片,为原图添加图片混排模式,颜色值设置为红色0XFFFF0000,混排模式设置为PorterDuff.Mode.DARKEN。

private void setPorterDuffColorFilter(Canvas canvas) {
        PorterDuffColorFilter colorFilter = new PorterDuffColorFilter(0XFFFF0000, PorterDuff.Mode.DARKEN);
        paint.setColorFilter(colorFilter);
        //获取图片
        Bitmap mBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.fj_img);
        canvas.drawBitmap(mBitmap, 50, 50, paint);
    }
技术分享
上面的图片就是运行之后的效果了,原图不仅变红了,而且还变暗了。其实我们这里将PorterDuffColorFilter的构造器参数拆开来分析一下,首先我们传递进去一个红色的颜色值0XFFFF0000,这里相当于创建了一张新的图层,图层的颜色就是0XFFFF0000,而我们的原图可以看作是第二张图层,我们先把这2个图片重叠放在一起,就会发现得到一个原图上很红的图片,然后我们看一下PorterDuff.Mode是DARKEN模式,表示在之前得到的“原图+很红”的图片上进一步将色调调成暗色,最终得到了如上所示的图片。

PorterDuff.Mode也提供了18种混排模式已经算法:

技术分享

Sa 代表 Source alpha (源透明度 -- 传入颜色的透明度),Da 代表 Destination alpha (目标 alpha),Sc 代表 Source Color (源颜色),Dc 代表 Destination Color (目标色);

注意:先绘制dst,再绘制src。

1.PorterDuff.Mode.CLEAR
    所绘制源图像不会提交到画布上。
2.PorterDuff.Mode.SRC
    只显示源图像。
3.PorterDuff.Mode.DST
    只显示目标图像。
4.PorterDuff.Mode.SRC_OVER
    正常绘制显示,源图像居上显示。
5.PorterDuff.Mode.DST_OVER
    上下层都显示。目标图像居上显示。
6.PorterDuff.Mode.SRC_IN
    取两层绘制交集中的源图像。
7.PorterDuff.Mode.DST_IN
     取两层绘制交集中的目标图像。
8.PorterDuff.Mode.SRC_OUT
    只在源图像和目标图像不相交的地方绘制源图像。
9.PorterDuff.Mode.DST_OUT
    只在源图像和目标图像不相交的地方绘制目标图像。
10.PorterDuff.Mode.SRC_ATOP
    在源图像和目标图像相交的地方绘制源图像,在不相交的地方绘制目标图像。
11.PorterDuff.Mode.DST_ATOP
   在源图像和目标图像相交的地方绘制目标图像而在不相交的地方绘制源图像。
12.PorterDuff.Mode.XOR
    异或:去除两图层交集部分
13.PorterDuff.Mode.DARKEN
     取两图层全部区域,交集部分颜色加深
14.PorterDuff.Mode.LIGHTEN
    取两图层全部,点亮交集部分颜色
15.PorterDuff.Mode.MULTIPLY
    取两图层交集部分叠加后颜色
16.PorterDuff.Mode.SCREEN

    滤色。

setFilterBitmap

setFilterBitmap(boolean filter):如果该项设置为true,则图像在动画进行中会滤掉对Bitmap图像的优化操作,加快显示速度

setFlags

setFlags(int flags):可以用来给Paint设置里面定义好的一些属性,如抗锯齿,防抖动等;

setMaskFilter

setMaskFilter(MaskFilter maskFilter):设置绘制时图片边缘效果,可以有模糊和浮雕;

MaskFilter类可以为Paint分配边缘效果。
        对MaskFilter的扩展可以对一个Paint边缘的alpha通道应用转换。Android包含了下面几种MaskFilter:

        BlurMaskFilter   指定了一个模糊的样式和半径来处理Paint的边缘;
        EmbossMaskFilter  指定了光源的方向和环境光强度来添加浮雕效果;

setPathEffect(控制绘制轮廓(线条))

setPathEffect(PathEffect effect):是用来控制绘制轮廓(线条)的方式:

这个类本身并没有做什么特殊的处理,只是继承了Object,通常我们使用的是它的几个子类,就是上面图片中所显示的。在使用的时候,通常是
PathEffect pe = new 一个具体的子类;
然后使用Paint的setPathEffect(PathEffect pe)方法即可。

CornerPathEffect:

这个类的作用就是将Path的各个连接线段之间的夹角用一种更平滑的方式连接,类似于圆弧与切线的效果;
一般的,通过CornerPathEffect(float radius)指定一个具体的圆弧半径来实例化一个CornerPathEffect;

private void setCornerPathEffect(Canvas canvas) {

        // 创建,并初始化Path
        Path mPath = new Path();
        mPath.moveTo(0, 0);
        for (int i = 1; i <= 15; i++)
        {
            // 生成15个点,随机生成它们的坐标,并将它们连成一条Path
            mPath.lineTo(i * 20, (float) Math.random() * 100);
        }
        paint.setColor(Color.BLACK);
        paint.setStrokeWidth(40);
        canvas.drawPath(mPath, paint);
        canvas.translate(0, 200);

        //使用CornerPathEffect路径效果--参数为圆角半径
        PathEffect mEffects = new CornerPathEffect(10);
        paint.setPathEffect(mEffects);
        paint.setColor(Color.BLUE);
        canvas.drawPath(mPath, paint);
    }
技术分享

DashPathEffect:

这个类的作用就是将Path的线段虚线化
构造函数为DashPathEffect(float[] intervals, float phase),其中intervals为虚线的ON和OFF数组,该数组的length必须大于等于2,phase为绘制时的偏移量。


DiscretePathEffect:

这个类的作用是打散Path的线段,使得在原来路径的基础上发生打散效果。
一般的,通过构造DiscretePathEffect(float segmentLength,float deviation)来构造一个实例,其中,segmentLength指定最大的段长,deviation指定偏离量。

private void setDiscretePathEffect(Canvas canvas) {

        // 创建,并初始化Path
        Path mPath = new Path();
        mPath.moveTo(0, 0);
        for (int i = 1; i <= 15; i++)
        {
            // 生成15个点,随机生成它们的坐标,并将它们连成一条Path
            mPath.lineTo(i * 20, (float) Math.random() * 100);
        }
        paint.setColor(Color.BLACK);
        paint.setStrokeWidth(20);
        canvas.drawPath(mPath, paint);
        canvas.translate(0, 100);

        // 初始化DiscretePathEffect -- segmentLength指定最大的段长,deviation指定偏离量
        PathEffect mEffects = new DiscretePathEffect(3.0f, 5.0f);
        paint.setPathEffect(mEffects);
        paint.setColor(Color.RED);
        canvas.drawPath(mPath, paint);
    }
技术分享

PathDashPathEffect:

这个类的作用是使用Path图形来填充当前的路径,其构造函数为PathDashPathEffect (Path shape, float advance, float phase,PathDashPathEffect.Stylestyle)。
shape则是指填充图形,advance指每个图形间的间距,phase为绘制时的偏移量,style为该类自由的枚举值,有三种情况:Style.ROTATE、Style.MORPH和Style.TRANSLATE;
其中ROTATE的情况下,线段连接处的图形转换以旋转到与下一段移动方向相一致的角度进行转转,MORPH时图形会以发生拉伸或压缩等变形的情况与下一段相连接,TRANSLATE时,图形会以位置平移的方式与下一段相连接。

private void setPathDashPathEffect(Canvas canvas) {

        // 创建,并初始化Path
        Path mPath = new Path();
        mPath.moveTo(0, 0);
        for (int i = 1; i <= 15; i++)
        {
            // 生成15个点,随机生成它们的坐标,并将它们连成一条Path
            mPath.lineTo(i * 20, (float) Math.random() * 60);
        }
        paint.setColor(Color.BLACK);
        canvas.drawPath(mPath, paint);
        canvas.translate(0, 100);

        Path p = new Path();
        p.addRect(0, 0, 8, 8, Path.Direction.CCW);
        // shape则是指填充图形,advance指每个图形间的间距,phase为绘制时的偏移量,style为该类自由的枚举值
        PathEffect mEffects = new PathDashPathEffect(p, 12, mPhase, PathDashPathEffect.Style.ROTATE);
        paint.setPathEffect(mEffects);
        paint.setColor(Color.GREEN);
        canvas.drawPath(mPath, paint);
    }
技术分享

ComposePathEffect:

组合效果,这个类需要两个PathEffect参数来构造一个实例,ComposePathEffect (PathEffect outerpe,PathEffect innerpe),表现时,会首先将innerpe表现出来,然后再在innerpe的基础上去增加outerpe的效果;

private void setComposePathEffect(Canvas canvas) {
        // 创建,并初始化Path
        Path mPath = new Path();
        mPath.moveTo(0, 0);
        for (int i = 1; i <= 15; i++)
        {
            // 生成15个点,随机生成它们的坐标,并将它们连成一条Path
            mPath.lineTo(i * 20, (float) Math.random() * 60);
        }
        // 初始化DiscretePathEffect -- segmentLength指定最大的段长,deviation指定偏离量
        PathEffect mEffect1 = new DiscretePathEffect(3.0f, 5.0f);

        Path p = new Path();
        p.addRect(0, 0, 8, 8, Path.Direction.CCW);
        // shape则是指填充图形,advance指每个图形间的间距,phase为绘制时的偏移量,style为该类自由的枚举值
        PathEffect mEffect2 = new PathDashPathEffect(p, 12, mPhase, PathDashPathEffect.Style.ROTATE);
        // 组合效果
        PathEffect mEffects = new ComposePathEffect(mEffect1, mEffect2);
        paint.setPathEffect(mEffects);
        paint.setColor(Color.GREEN);
        canvas.drawPath(mPath, paint);

    }
技术分享

SumPathEffect:

叠加效果,这个类也需要两个PathEffect作为参数SumPathEffect(PathEffect first,PathEffect second),但与ComposePathEffect不同的是,在表现时,会分别对两个参数的效果各自独立进行表现,然后将两个效果简单的重叠在一起显示出来;

private void setSumPathEffect(Canvas canvas) {
        // 创建,并初始化Path
        Path mPath = new Path();
        mPath.moveTo(0, 0);
        for (int i = 1; i <= 15; i++)
        {
            // 生成15个点,随机生成它们的坐标,并将它们连成一条Path
            mPath.lineTo(i * 20, (float) Math.random() * 60);
        }

        Path p = new Path();
        p.addRect(0, 0, 8, 8, Path.Direction.CCW);
        // shape则是指填充图形,advance指每个图形间的间距,phase为绘制时的偏移量,style为该类自由的枚举值
        PathEffect mEffect1 = new PathDashPathEffect(p, 12, 0f, PathDashPathEffect.Style.ROTATE);
        // 初始化DashPathEffect --intervals为虚线的ON和OFF数组,offset为绘制时的偏移量
        PathEffect mEffect2 = new DashPathEffect(new float[] {
                20, 10, 5, 10
        }, 0f);
        // 叠加效果
        PathEffect mEffects = new SumPathEffect(mEffect1, mEffect2);
        paint.setPathEffect(mEffects);
        paint.setColor(Color.GREEN);
        canvas.drawPath(mPath, paint);
    }
技术分享

setShader(渐变效果)

setShader(Shader shader); 设置图像效果,使用Shader可以绘制出各种渐变效果;

Shader下面有五个子类可用:

BitmapShader :位图图像渲染

LinearGradient:线性渲染

RadialGradient:环形渲染

SweepGradient:扫描渐变渲染/梯度渲染

ComposeGradient:组合渲染,可以和其他几个子类组合起来使用

这几个类中LinearGradient、RadialGradient、SweepGradient均是可以将颜色进行处理,形成柔和的过渡,也可以称为渐变,而BitmapShader 则是直接使用位图进行渲染,就类似于贴图,在贴图的过程中根据需要自然就可以选择相应的模式,有三种模式可供选择,分别是:

枚举:
emun Shader.TileMode

定义了平铺的3种模式:
static final Shader.TileMode CLAMP: 边缘拉伸,即使用边缘的最后一个像素进行延展;

static final Shader.TileMode MIRROR:在水平方向和垂直方向交替景象, 两个相邻图像间没有缝隙,从名称上看就像照镜子一样;

Static final Shader.TillMode REPETA:在水平方向和垂直方向重复摆放,两个相邻图像间有缝隙缝隙;

LinearGradient(线性渲染--也叫线性渐变)

public LinearGradient(float x0, float y0, float x1, float y1, int colors[], float positions[],  
               TileMode tile)  
float x0 :渐变的x坐标起点
float y0 :渐变的y坐标起点
float x1 :渐变的x坐标终点
float y1 :渐变的y坐标终点
int colors[]:渐变的颜色数组
float positions[]:颜色的相对位置

我们在PS上如果要拉出一条线性渐变,只需要先把渐变模式选为线性,然后拉出一条渐变线,同理,在android中,只需要一个起始点和一个终点即可确定一条渐变线

private void setLinearGradient(Canvas canvas) {
        // 定义起始和最终颜色
        int mStartColor = 0xff0000ff; //蓝色
        int mToColor = 0xffff0000;  //红色
        int rightBottomY = 400;
        int rightBottomX = 400;

        canvas.save();
        paint.setColor(Color.BLACK);
        paint.setTextSize(36);
        canvas.drawText("Shader.TileMode.CLAMP",rightBottomX+30,rightBottomY/2,paint);
        Shader linearGradient = new LinearGradient(80, rightBottomY/2, rightBottomX, rightBottomY/2, mStartColor, mToColor, Shader.TileMode.CLAMP);
        paint.setShader(linearGradient);
        canvas.drawRect(0, 0, rightBottomX, rightBottomY,paint);
        canvas.restore();

        canvas.save();
        canvas.translate(0,450);
        paint.setColor(Color.BLACK);
        paint.setTextSize(36);
        canvas.drawText("Shader.TileMode.MIRROR",rightBottomX+30,rightBottomY/2,paint);
        linearGradient = new LinearGradient(80, rightBottomY/2, rightBottomX, rightBottomY/2, mStartColor, mToColor, Shader.TileMode.MIRROR);
        paint.setShader(linearGradient);
        canvas.drawRect(0, 0, rightBottomX, rightBottomY,paint);
        canvas.restore();

        canvas.save();
        canvas.translate(0,900);
        paint.setColor(Color.BLACK);
        paint.setTextSize(36);
        canvas.drawText("Shader.TileMode.REPEAT",rightBottomX+30,rightBottomY/2,paint);
        linearGradient = new LinearGradient(80, rightBottomY/2, rightBottomX, rightBottomY/2, mStartColor, mToColor, Shader.TileMode.REPEAT);
        paint.setShader(linearGradient);
        canvas.drawRect(0, 0, rightBottomX, rightBottomY,paint);
        canvas.restore();
    }
技术分享

RadialGradient (环形渲染):

  RadialGradient(float x, float y, float radius,  
                              int colors[], float positions[], TileMode tile)  
x:渐变的中心x坐标
y:渐变的中心y坐标
radius:渐变的半径
colors:梯度渐变的颜色数组
positions:和LinearGradient类似,用来指定颜色数组的相对位置
private void setRadialGradient(Canvas canvas) {
        int rightBottomY = 400;
        int rightBottomX = 400;

        canvas.save();
        paint.setColor(Color.BLACK);
        paint.setTextSize(36);
        canvas.drawText("Shader.TileMode.CLAMP",rightBottomX+30,rightBottomY/2,paint);
        Shader radialGradient = new RadialGradient(rightBottomX/2, rightBottomY/2, 200, new int[] {
                Color.YELLOW, Color.RED, Color.BLUE, Color.GREEN }, null,
                Shader.TileMode.CLAMP);
        paint.setShader(radialGradient);
        canvas.drawRect(0, 0, rightBottomX, rightBottomY,paint);
        canvas.restore();

        canvas.save();
        canvas.translate(0,450);
        paint.setColor(Color.BLACK);
        paint.setTextSize(36);
        canvas.drawText("Shader.TileMode.MIRROR",rightBottomX+30,rightBottomY/2,paint);
        radialGradient = new RadialGradient(rightBottomX/2, rightBottomY/2, 200, new int[] {
                Color.YELLOW, Color.RED, Color.BLUE, Color.GREEN }, null,
                Shader.TileMode.MIRROR);
        paint.setShader(radialGradient);
        canvas.drawRect(0, 0, rightBottomX, rightBottomY,paint);
        canvas.restore();

        canvas.save();
        canvas.translate(0,900);
        paint.setColor(Color.BLACK);
        paint.setTextSize(36);
        canvas.drawText("Shader.TileMode.REPEAT",rightBottomX+30,rightBottomY/2,paint);
        radialGradient = new RadialGradient(rightBottomX/2, rightBottomY/2, 200, new int[] {
                Color.YELLOW, Color.RED, Color.BLUE, Color.GREEN }, null,
                Shader.TileMode.REPEAT);
        paint.setShader(radialGradient);
        canvas.drawRect(0, 0, rightBottomX, rightBottomY,paint);
        canvas.restore();
    }
技术分享

SweepGradient(扫描渐变渲染/梯度渲染)

    SweepGradient(float cx, float cy,  
                             int colors[], float positions[])  
 cx,cy:扫描中心的x,y坐标
colors:渐变的数组颜色
positions:渐变的相对位置
private void setSweepGradient(Canvas canvas) {
        Shader sweepGradient = new SweepGradient(400, 400, new int[] { Color.YELLOW,
                Color.RED, Color.BLUE, Color.GREEN }, new float[] { 0, 0.2f,0.6f, 0.9f });
        paint.setShader(sweepGradient);
        canvas.drawCircle(400, 400, 300, paint);
    }
技术分享

BitmapShader(位图渲染)

BitmapShader(Bitmap bitmap, TileMode tileX, TileMode tileY)
第一个参数是Bitmap对象,该Bitmap决定了用什么图片对绘制的图形进行贴图
第二个参数和第三个参数都是Shader.TileMode类型的枚举值,有以下三个取值:CLAMP 、REPEAT 和 MIRROR
private void setBitmapShader(Canvas canvas) {
        canvas.save();
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.fj_img);
        Shader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP,
                Shader.TileMode.CLAMP);
        paint.setShader(bitmapShader);
        canvas.drawRect(0, 0, getWidth(), 400,paint);
        paint.reset();
        paint.setColor(Color.RED);
        paint.setTextSize(36);
        canvas.drawText("tileX=CLAMP;tileY=CLAMP",20,60,paint);
        canvas.restore();

        canvas.save();
        canvas.translate(0,450);
        bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.fj_img);
        bitmapShader = new BitmapShader(bitmap, Shader.TileMode.MIRROR,
                Shader.TileMode.MIRROR);
        paint.setShader(bitmapShader);
        canvas.drawRect(0, 0, getWidth(), 400,paint);
        paint.reset();
        paint.setColor(Color.RED);
        paint.setTextSize(36);
        canvas.drawText("tileX=MIRROR;tileY=MIRROR",20,60,paint);
        canvas.restore();

        canvas.save();
        canvas.translate(0,900);
        bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.fj_img);
        bitmapShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT,
                Shader.TileMode.REPEAT);
        paint.setShader(bitmapShader);
        canvas.drawRect(0, 0, getWidth(), 400,paint);
        paint.reset();
        paint.setColor(Color.RED);
        paint.setTextSize(36);
        canvas.drawText("tileX=REPEAT;tileY=REPEAT",20,60,paint);
        canvas.restore();

        canvas.save();
        canvas.translate(0,1350);
        bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.fj_img);
        bitmapShader = new BitmapShader(bitmap, Shader.TileMode.MIRROR,
                Shader.TileMode.REPEAT);
        paint.setShader(bitmapShader);
        canvas.drawRect(0, 0, getWidth(), 400,paint);
        paint.reset();
        paint.setColor(Color.RED);
        paint.setTextSize(36);
        canvas.drawText("tileX=MIRROR;tileY=REPEAT",20,60,paint);
        canvas.restore();
    }
技术分享

ComposeGradient(组合渲染)

ComposeShader(Shader shaderA, Shader shaderB, PorterDuff.Mode mode)
ComposeShader(Shader shaderA, Shader shaderB, Xfermode mode)
private void setComposeShader(Canvas canvas) {

        canvas.save();
        //创建位图
        Bitmap mBitmap = ((BitmapDrawable) getResources().getDrawable(R.mipmap.fj_img)).getBitmap();
        //将图scale成我们想要的大小
        mBitmap = Bitmap.createScaledBitmap(mBitmap, 400, 400, false);

        // 创建位图渲染
        BitmapShader bitmapShader = new BitmapShader(mBitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
        paint.setShader(bitmapShader);
        canvas.drawCircle(200, 200, 200, paint);
        canvas.restore();

        canvas.save();
        canvas.translate(0,450);

        // 创建位图渲染
        bitmapShader = new BitmapShader(mBitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
        // 创建环形渐变
        RadialGradient radialGradient = new RadialGradient(200, 200, 200,
                Color.TRANSPARENT, Color.WHITE, Shader.TileMode.MIRROR);
        // 创建组合渐变,由于直接按原样绘制就好,所以选择Mode.SRC_OVER
        ComposeShader composeShader = new ComposeShader(bitmapShader, radialGradient,
                PorterDuff.Mode.SRC_OVER);
        // 将组合渐变设置给paint
        paint.setShader(composeShader);
        canvas.drawCircle(200, 200, 200, paint);
        canvas.restore();
    }
技术分享










参考博文:http://blog.csdn.net/tianjian4592/article/details/44336949

Paint基本用法