自定义View(二)- Paint

自定义View(一)- 流程

在上一篇文章中我们分析了自定义View的流程,这片文章我们来分析一下绘制过程中的 Paint 类的API

Paint API

我们只看一些常用的API

1. setColor 设置画笔的颜色
  void setColor(@ColorInt int color)
2. setARGB 设置画笔的ARGB值
/**
*   a,r,g,b的取值范围都是0~255
*/
  void setARGB(int a, int r, int g, int b)
3. setAlpha 设置画笔的透明度,0为透明
/**
*   a的取值范围都是0~255
*/
  void setAlpha(int a)
4. setAntiAlias 设置是否抗锯齿
  void setAntiAlias(boolean aa)
5. setDither 设置是否防抖动,设置true会图像更加平滑饱满,图像更清晰
  void setDither(boolean dither)
6. setStyle 设置画笔的样式
  void setStyle(Style style)

以下为画笔的样式,我们以使用宽为b的画笔绘制一个半径为r的园为例。

  • Paint.Style.FILL 绘制一个半径为r的圆
  • Paint.Style.STROKE 绘制一个内径为(r-b/2)宽为b的圆环
  • Paint.Style.FILL_AND_STROKE 绘制一个半径为(r+b/2)的圆
7. setStrokeWidth 设置画笔的宽
  void setStrokeWidth(float width)
8. setStrokeJoin 设置折线处的样式
  void setStrokeJoin(Join join)
image.png
9.setStrokeCap 设置线帽
void setStrokeCap(Cap cap)
image.png
10.setFilterBitmap 设置双线性过滤 true时提高图片的过渡效果
void setFilterBitmap(boolean filter)
image.png
11. setXfermode 设置图层混合模式
image.png

上图是16中混合模式,还有两种不常用的。接下来我们一一介绍。图中的黄色的圆为dst(先绘制的)目标图,蓝色的矩形是src(后绘制的)源图。所有的模式都是作用在src上面的。
PorterDuff.mode.CLEAR 清除src源图及相交部分
PorterDuff.mode.SRC 显示src源图
PorterDuff.mode.DST 显示dst目标图
PorterDuff.mode.SRC_OVER dst、src都显示src在上层
PorterDuff.mode.DST_OVER dst、src都显示dst在上层
PorterDuff.mode.SRC_IN src在上层显示并清除src的非交集部分
PorterDuff.mode.DST_IN src在下层显示并清除src的非交集部分
PorterDuff.mode.SRC_OUT 显示src的非交集部分,交集部分透明
PorterDuff.mode.DST_OUT 清除src的非交集部分,交集部分透明
PorterDuff.mode.SRC_ATOP 取src的交集部分和dst的非交集部分
PorterDuff.mode.DST_ATOP 取dst的交集部分和src的非交集部分
PorterDuff.mode.XOR 交集部分变透明
PorterDuff.mode.DARKEN 交集部分颜色加深
PorterDuff.mode.LIGHTEN 交集部分颜色变亮
PorterDuff.mode.MULTIPLY 取交集部分颜色叠加
PorterDuff.mode.SCREEN 交集部分滤色
PorterDuff.mode.ADD 交集部分饱和度相加
PorterDuff.mode.OVER 交集部分叠加

12. setShader 设置着色器
  Shader setShader(Shader shader)

我们分析一下系统提供的Shader的子类

  • LinearGradient 线性渐变
LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorInt int colors[],
@Nullable float positions[], @NonNull TileMode tile)

x0,y0 表示开始点的位置
x1,y1表示结束点的位置
colors[] 颜色的数组
positions[] 指定各开始的颜色的位置取值范围 0~1,为null时颜色均匀分布
TileMode 表示重复模式 (CLAMP 重复最后一个像素点、REPEAT 整个重复、MIRROR 镜像重复)

 LinearGradient(float x0, float y0, float x1, float y1,@ColorInt int color0,
 @ColorInt int color1,@NonNull TileMode tile)

该构造函数只能指定两个颜色
构造函数中两个点的连线方向决定了颜色的渐变方向。

 paint.setShader(new LinearGradient(0,0,500,0,new int[]{Color.RED,Color.YELLOW},
          new float[]{0,1}, Shader.TileMode.REPEAT));
 canvas.drawRect(0,0,1000,1000,paint);
image.png
  • SweepGradient 扫描式渐变
SweepGradient(float cx, float cy,
            @NonNull @ColorInt int colors[], @Nullable float positions[])

cx,cy 表示圆心
colors 表示渐变颜色的数组
positions 各颜色开始的位置0~1

SweepGradient(float cx, float cy, @ColorInt int color0, @ColorInt int color1)

设置两个颜色的构造函数

paint.setShader(new SweepGradient(500,500,new int[]{Color.RED,Color.YELLOW},new float[]{0,1}));
canvas.drawRect(0,0,1000,1000,paint);
image.png
  • RadialGradient 径向渐变
RadialGradient(float centerX, float centerY, float radius,@NonNull @ColorInt int colors[],
 @Nullable float stops[],@NonNull TileMode tileMode)

centerX,centerY 指定一个圆心
radius 指定半径
colors 指定颜色的数组
stops 指定每个颜色的结束位置
TileMode 重复模式

RadialGradient(float centerX, float centerY, float radius,
            @ColorInt int centerColor, @ColorInt int edgeColor, @NonNull TileMode tileMode)

指定两个颜色的构造函数

paint.setShader(new RadialGradient(500, 500, 300, new int[]{Color.RED, Color.YELLOW}, new float[]{0, 1}, Shader.TileMode.REPEAT));
canvas.drawRect(0, 0, 1000, 1000, paint);
image.png
  • BitmapGradient 位图着色器
BitmapShader(@NonNull Bitmap bitmap, @NonNull TileMode tileX, @NonNull TileMode tileY)

bitmap 指定一个位图
tileX X方向的重复模式
tileY Y方向的重复模式

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bitmap);
//X、Y方向都重复
paint.setShader(new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT));
canvas.drawRect(0, 0, 1000, 1000, paint);
image.png
  • ComposeShader 混合着色器
ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, @NonNull Xfermode mode)
ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, @NonNull PorterDuff.Mode mode)

shaderA 着色器,混合模式中的dst
shaderB 着色器,混合模式中的src
Xfermode、PorterDuff.Mode 混合模式。Xfermode是一个基类使用时我们使用其子类PorterDuffXfermode。

LinearGradient linearGradient = new LinearGradient(0, 0, 500, 0, new int[]{Color.RED, Color.YELLOW}, new float[]{0, 1}, Shader.TileMode.REPEAT);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bitmap);
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
paint.setShader(new ComposeShader(linearGradient,bitmapShader,new PorterDuffXfermode(PorterDuff.Mode.ADD)));
canvas.drawRect(0, 0, 1000, 1000, paint);
image.png
13. setColorFilter()设置滤镜效果
ColorFilter setColorFilter(ColorFilter filter)
  • LightingColorFilter
 //LightingColorFilter 滤镜
 //LightingColorFilter(@ColorInt int mul, @ColorInt int add)
 //mul和add都是和颜色值格式相同的int。mul用来和目标颜色值相乘,add是用来和目标颜色值相加
 //R' = R*mul.R/0xff + add.R
 //G' = G*mul.G/0xff + add.G
 //B' = B*mul.B/0Xff + add.B
 //mull 为0xffffff  add为0x000000  时显示的是原图效果
 //要降低某颜色值的效果时修改mul的值,增加修改add对应的值
  LightingColorFilter lightingColorFilter = new LightingColorFilter(0xffffff, 0x000000);
  • PorterDuffColorFilter
 //PorterDuffColorFilter 滤镜
 //PorterDuffColorFilter(@ColorInt int color, @NonNull PorterDuff.Mode mode)
 //相当于先创建一个颜色为color的图层,然后使用mode进行图层混合
 PorterDuffColorFilter duffColorFilter = new PorterDuffColorFilter(0xffff0000, PorterDuff.Mode.DARKEN);
  • ColorMatrixColorFilter
        //ColorMatrixColorFilter(@NonNull float[] array)  使用一个矩阵数组的构造函数
        //ColorMatrixColorFilter 颜色矩阵
        //使用一个20位的float数组来表示颜色矩阵
        //[
        //   a,b,c,d,e,
        //   f,g,h,i,j,
        //   k,l,m,n,o,
        //   p,q,r,s,t
        // ]
        //使用颜色矩阵的计算方式为
        // R' = R*a+G*b+B*c+A*d+e;
        // G' = R*f+G*g+B*h+A*i+j;
        // B' = R*k+G*l+B*m+A*n+o;
        // A' = R*p+G*q+B*r+A*s+t;
        //设置下面的颜色矩阵原图不变
        //float[] floats = {
        //       1, 0, 0, 0, 0,
        //       0, 1, 0, 0, 0,
        //       0, 0, 1, 0, 0,
        //       0, 0, 0, 1, 0
        //}
        float[] floats = {
                1, 0, 0, 0, 0,
                0, 1, 0, 0, 0,
                0, 0, 1, 0, 0,
                0, 0, 0, 1, 0
        };
        ColorMatrixColorFilter colorFilter = new ColorMatrixColorFilter(floats);

        //ColorMatrixColorFilter(@NonNull ColorMatrix matrix)  使用ColorMatrix的构造函数
        ColorMatrix cm = new ColorMatrix();
        //修改颜色矩阵,该方法也是操作的颜色矩阵的数组
        //r,g,b,a修改是数组中对应的a[0],g[6],m[12],s[18]
        cm.setScale(1,1,1,1);
        //设置饱和度
        //0 为灰色,1 为原色, >1增加饱和度
        cm.setSaturation(0);
        //通过旋转颜色的坐标系来改变颜色矩阵
        //0 表示旋转red  1 表示旋转green  2表示旋转blue
        cm.setRotate(0,100);
        ColorMatrixColorFilter colorFilter = new ColorMatrixColorFilter(cm);

常见的滤镜效果

 // 黑白
    public static final float colormatrix_heibai[] = {
            0.8f, 1.6f, 0.2f, 0, -163.9f,
            0.8f, 1.6f, 0.2f, 0, -163.9f,
            0.8f, 1.6f, 0.2f, 0, -163.9f,
            0, 0, 0, 1.0f, 0};
    // 复古
    public static final float colormatrix_fugu[] = {
            0.9f, 0.0f, 0.0f, 0.0f, 0.0f,
            0.0f, 0.8f, 0.0f, 0.0f, 0.0f,
            0.0f, 0.0f, 0.5f, 0.0f, 0.0f,
            0, 0, 0, 1.0f, 0};
    // 哥特
    public static final float colormatrix_gete[] = {
            1.9f, -0.3f, -0.2f, 0, -87.0f,
            -0.2f, 1.7f, -0.1f, 0, -87.0f,
            -0.1f, -0.6f, 2.0f, 0, -87.0f,
            0, 0, 0, 1.0f, 0};
    // 传统
    public static final float colormatrix_chuan_tong[] = {
            1.0f, 0.0f, 0.0f, 0, -10f,
            0.0f, 1.0f, 0.0f, 0, -10f,
            0.0f, 0.0f, 1.0f, 0, -10f,
            0, 0, 0, 1, 0};
    // 淡雅
    public static final float colormatrix_danya[] = {
            0.6f, 0.3f, 0.1f, 0, 73.3f,
            0.2f, 0.7f, 0.1f, 0, 73.3f,
            0.2f, 0.3f, 0.4f, 0, 73.3f,
            0, 0, 0, 1.0f, 0};
    // 光晕
    public static final float colormatrix_guangyun[] = {
            0.9f, 0, 0, 0, 64.9f,
            0, 0.9f, 0, 0, 64.9f,
            0, 0, 0.9f, 0, 64.9f,
            0, 0, 0, 1.0f, 0};
    // 胶片
    public static final float colormatrix_fanse[] = {
            -1.0f, 0.0f, 0.0f, 0.0f, 255.0f,
            0.0f, -1.0f, 0.0f, 0.0f, 255.0f,
            0.0f, 0.0f, -1.0f, 0.0f, 255.0f,
            0.0f, 0.0f, 0.0f, 1.0f, 0.0f};
    // 褐片
    public static final float colormatrix_hepian[] = {
            1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
            0.0f, 0.8f, 0.0f, 0.0f, 0.0f,
            0.0f, 0.0f, 0.8f, 0.0f, 0.0f,
            0, 0, 0, 1.0f, 0};
    // 怀旧
    public static final float colormatrix_huajiu[] = {
            0.2f, 0.5f, 0.1f, 0, 40.8f,
            0.2f, 0.5f, 0.1f, 0, 40.8f,
            0.2f, 0.5f, 0.1f, 0, 40.8f,
            0, 0, 0, 1, 0};
    // 胶片2
    public static final float colormatrix_jiao_pian[] = {
            0.71f, 0.2f, 0.0f, 0.0f, 60.0f,
            0.0f, 0.94f, 0.0f, 0.0f, 60.0f,
            0.0f, 0.0f, 0.62f, 0.0f, 60.0f,
            0, 0, 0, 1.0f, 0};
    // 蓝调
    public static final float colormatrix_landiao[] = {
            2.1f, -1.4f, 0.6f, 0.0f, -71.0f,
            -0.3f, 2.0f, -0.3f, 0.0f, -71.0f,
            -1.1f, -0.2f, 2.6f, 0.0f, -71.0f,
            0.0f, 0.0f, 0.0f, 1.0f, 0.0f};
    // 浪漫
    public static final float colormatrix_langman[] = {
            0.9f, 0, 0, 0, 63.0f,
            0, 0.9f, 0, 0, 63.0f,
            0, 0, 0.9f, 0, 63.0f,
            0, 0, 0, 1.0f, 0};
    // 锐色
    public static final float colormatrix_ruise[] = {
            4.8f, -1.0f, -0.1f, 0, -388.4f,
            -0.5f, 4.4f, -0.1f, 0, -388.4f,
            -0.5f, -1.0f, 5.2f, 0, -388.4f,
            0, 0, 0, 1.0f, 0};
    // 梦幻
    public static final float colormatrix_menghuan[] = {
            0.8f, 0.3f, 0.1f, 0.0f, 46.5f,
            0.1f, 0.9f, 0.0f, 0.0f, 46.5f,
            0.1f, 0.3f, 0.7f, 0.0f, 46.5f,
            0.0f, 0.0f, 0.0f, 1.0f, 0.0f};
    // 清宁
    public static final float colormatrix_qingning[] = {
            0.9f, 0, 0, 0, 0,
            0, 1.1f, 0, 0, 0,
            0, 0, 0.9f, 0, 0,
            0, 0, 0, 1.0f, 0};

    // 夜色
    public static final float colormatrix_yese[] = {
            1.0f, 0.0f, 0.0f, 0.0f, -66.6f,
            0.0f, 1.1f, 0.0f, 0.0f, -66.6f,
            0.0f, 0.0f, 1.0f, 0.0f, -66.6f,
            0.0f, 0.0f, 0.0f, 1.0f, 0.0f};
    // 酒红
    public static final float colormatrix_jiuhong[] = {
            1.2f, 0.0f, 0.0f, 0.0f, 0.0f,
            0.0f, 0.9f, 0.0f, 0.0f, 0.0f,
            0.0f, 0.0f, 0.8f, 0.0f, 0.0f,
            0, 0, 0, 1.0f, 0};

    // 湖光掠影
    public static final float colormatrix_huguang[] = {
            0.8f, 0.0f, 0.0f, 0.0f, 0.0f,
            0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
            0.0f, 0.0f, 0.9f, 0.0f, 0.0f,
            0, 0, 0, 1.0f, 0};
    // 泛黄
    public static final float colormatrix_huan_huang[] = {
            1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
            0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
            0.0f, 0.0f, 0.5f, 0.0f, 0.0f,
            0, 0, 0, 1.0f, 0};
image.png

image.png

image.png

image.png
14.setMaskFilter 这是边缘效果,是用该方法前要关闭硬件加速setLayerType(LAYER_TYPE_SOFTWARE,null);
MaskFilter setMaskFilter(MaskFilter maskfilter)
  • BlurMaskFilter 对图层的边缘进行模糊处理
//radius   模糊半径
//blur       模糊处理的模式
//NORMAL  向目标内外模糊radius宽的地方,内外延伸的延伸均取自目标的边缘颜色
//INNER   向目标内部延伸radius宽,取目标边缘外的颜色
//OUTER  向目标外部延伸radius宽,取目标边缘的颜色,显示目标
//SOLID  向目标外部延伸radius宽,取目标的颜色,不显示目标
BlurMaskFilter(float radius, Blur style)

使用上面的模式在黑色的矩形内绘制一个图片


image.png
  • EmbossMaskFilter 实现浮雕效果
//direction 表示光源的位置
//ambient  环境光照强度 0~1
//specular  反射等级  值越小越亮 
//blurRadius 照亮前的模糊量,就是光照中亮边的宽度
EmbossMaskFilter(float[] direction, float ambient, float specular, float blurRadius)
image.png
15. setTextSize 设置字体的大小
void setTextSize(float textSize)
16.setTextScaleX 设置字体的缩放比例
void setTextScaleX(float scaleX) 
17. setTextAlign 设置文本的对齐方式
void setTextAlign(Align align)
18. setUnderlineText 添加下划线
void setUnderlineText(boolean underlineText)
19. setStrikeThruText 添加删除线
void setStrikeThruText(boolean strikeThruText)
20. getTextBounds 获取文本的Rect值,该方法会将测算好的left、top、right、bottom封装到Rect中
void getTextBounds(String text, int start, int end, Rect bounds)
getTextBounds(char[] text, int index, int count, Rect bounds)
21. getFontMetrics 获取字体度量的对象
FontMetrics getFontMetrics()
public static class FontMetrics {
       /**
        * The maximum distance above the baseline for the tallest glyph in
        * the font at a given text size.
        */
       public float   top;
       /**
        * The recommended distance above the baseline for singled spaced text.
        */
       public float   ascent;
       /**
        * The recommended distance below the baseline for singled spaced text.
        */
       public float   descent;
       /**
        * The maximum distance below the baseline for the lowest glyph in
        * the font at a given text size.
        */
       public float   bottom;
       /**
        * The recommended additional space to add between lines of text.
        */
       public float   leading;
   }
image.png
22. measureText 获取文本的宽度
float measureText(char[] text, int index, int count)
float measureText(String text, int start, int end)
float measureText(String text)
float measureText(CharSequence text, int start, int end)

该文并没有将所有的API都罗列出来,剩下的API可查看官方文档Paint_API

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容