Android 自定义view基础之Paint 类

1,444 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第7天,点击查看活动详情

Android 自定义view 大致会经历 measure :对 view进行测量 ,Layout:对测量后的view 进行摆放 ,draw:在画布上进行具体的绘制

接下来在draw 方法中 会传入 一个canvas 参数 ,这个canvas就是所有绘制的基础 ,然而canvas 的绘制的api之中都有一个参数paint,这个paint 参数就可以设置所绘画内容的颜色 ,粗细,字形,质量.....

可以理解为canvas 是绘画的骨架 ,paint 来进行上色

paint类常用方法

设置绘制模式

  • Paint.setStyle(Style style) 设置绘制模式

    参数

    • Paint.Style.STROKE 划线模式(不填充)
    • Paint.Style.FILL 填充模式 (默认)
    • FILL_AND_STROKE

    设置颜色

    • Paint.setColor("颜色")

      • 可以用Clolor.BLACK(内部自带的静态对象)
      • 也可以Color.Prase("#88880000")
    • Paint.setARGB(a,r,g,b);

      • 四个参数值均为int 类型 分别为 透明度 和 RGB三元素

设置抗锯齿

  • Paint.setAniAlias(boolean a) 设置抗锯齿开关

总体来说开启看锯齿后绘制的图形会变的更加丝滑一些,所以此项应该开启

  • 也可以:

    Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    

其他一些常用API

  • Paint.setTextSize(float textSize) 设置文字大小
  • Paint.setStrokeWidth(float width) 设置线条宽度

paint 设置颜色渐变

1.1 线性渐变

构造方法: LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1, Shader.TileMode tile)

参数: x0 y0 x1 y1:渐变的两个端点的位置 color0 color1 是端点的颜色 tile:端点范围之外的着色规则,类型是 TileModeTileMode 一共有 3 个值可选: CLAMP, MIRRORREPEATCLAMP 会在端点之外延续端点处的颜色 (这个单词好奇怪 是不是?);MIRROR 是镜像模式;REPEAT 是重复模式。

Shader shader = new LinearGradient(0, 0, 400, 400, Color.parseColor("#E91E63"),
        Color.parseColor("#2196F3"), Shader.TileMode.CLAMP);
paint.setShader(shader);

利用线性渐变我们可以实现如下效果 ,tag 标签 渐变颜色

image.png

关于tag 标签如何使用可以查看我的另外一篇文章 RecyclerView分割线详解| 青训营笔记 - 掘金 (juejin.cn)

1.2 辐射渐变:

Shader shader = new RadialGradient(300, 300, 200, Color.parseColor("#E91E63"),
        Color.parseColor("#2196F3"), Shader.TileMode.CLAMP);
paint.setShader(shader);
​
...
​
canvas.drawCircle(300, 300, 200, paint);  

构造方法: RadialGradient(float centerX, float centerY, float radius, int centerColor, int edgeColor, TileMode tileMode)

参数: centerX centerY:辐射中心的坐标 radius:辐射半径 centerColor:辐射中心的颜色 edgeColor:辐射边缘的颜色 tileMode:辐射范围之外的着色模式。

sweepGradient 扫描渐变

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

参数: cx cy :扫描的中心 color0:扫描的起始颜色 color1:扫描的终止颜色

BitmapShader(bitmap 着色器)

可以于绘制圆形图像

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bitmap);
Shader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
paint.setShader(shader);
​
...
​
canvas.drawCircle(300, 300, 200, paint);//可以绘制圆形图片
//除此之外可以绘制不同形状的图片

构造方法: BitmapShader(Bitmap bitmap, Shader.TileMode tileX, Shader.TileMode tileY)

参数: bitmap:用来做模板的 Bitmap 对象 tileX:横向的 TileMode tileY:纵向的 TileMode

Matrix matrix=new Matrix();
matrix.setScale(scaleX,scaleY);
shader.setLocalMatrix(matrix);//设置放缩
paint.setStyle(Paint.Style.FILL);
paint.setShader(shader);

在shader 我们说指定的绘制区域 只要我们的画笔经过都会是渐变颜色

setColorFilter

这个可以理解为一种对自定义view绘制内容的滤镜效果

Paint.setColorFilter(ColorFilter filter)

这里的 filter是使用他的子类LightingColorFilter PorterDuffColorFilterColorMatrixColorFilter

  • LightingColorFilter

    源码文档

    /**
     * Create a colorfilter that multiplies the RGB channels by one color,
     * and then adds a second color. The alpha components of the mul and add
     * arguments are ignored.
     */
    public LightingColorFilter(@ColorInt int mul, @ColorInt int add) {
        mMul = mul;
        mAdd = add;
    }
    

简单来说mul 用来和目标像素相乘,add 用来和目标像素相加

这段代码修饰的Paint画出的图为原图

paint=new Paint();
ColorFilter lightingColorFilter = new LightingColorFilter(0xffffff, 0x000000);//乘的倍数为1 ,加的数值为0
paint.setColorFilter(lightingColorFilter);

效果

image.png

例如 绘制一张图片,我们添加蓝色的滤镜效果 把add参数的中间两位改为ff

public class myView extends View {
    public myView(Context context) {
        super(context);
    }

![image.png](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f3ba8a5f38124514a9c5e5e0afcc2457~tplv-k3u1fbpfcp-watermark.image?)
    public myView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public myView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    Bitmap bitmap;
    Paint paint;
    {
        bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.bitmap);
        paint=new Paint();
        ColorFilter lightingColorFilter = new LightingColorFilter(0xffffff, 0x00ff00);
        paint.setColorFilter(lightingColorFilter);
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.save();
        canvas.scale(0.5f,0.5f);
        canvas.drawBitmap(bitmap,0,0,paint);
        canvas.restore();
    }
}

效果如图 image.png

ox 即代表 这个数为16进制的数,由这个数的位数可以看出,这个数只有RGB通道,并没有 alpha 通道

参考 rengwuxian.com/ui-1-2/