Paint画笔高级应用(仅做学习笔记,以后做扩展的时候详细写)

先熟悉paint的属性:

 setARGB(255,255,255,0) 通过ARGB设置颜色
 alpha = 200//设置不透明度,范围0-255
 isAntiAlias=true//抗锯齿
 style=Paint.Style.FILL//描边效果
 strokeWidth=4f//描边宽度
 strokeCap= Paint.Cap.ROUND//画笔结尾的时候形状这里设置圆形
 strokeJoin= Paint.Join.MITER//拐角风格  //miter是锐角相交 还有圆角相交,直线相交
 shader = SweepGradient(200f,200f,Color.BLUE,Color.RED)//设置环形渲染器
 xfermode = PorterDuffXfermode(PorterDuff.Mode.DARKEN)//设置图层混合模式
 colorFilter = LightingColorFilter(0x00ffff,0x000000)//设置颜色过滤器
 isFilterBitmap=true//设置双线性过滤
 maskFilter = BlurMaskFilter(10f,BlurMaskFilter.Blur.NORMAL)//设置画笔这招滤镜,传入度数和样式
 textScaleX= 2f//设置文本缩放倍数
 textSize=38f
 textAlign= Paint.Align.LEFT//对其方式
 isUnderlineText= true//设置下划线
 val temp= "我在学习安卓进阶技术"
 val rect = Rect()
 getTextBounds(temp,0,temp.length,rect)//测量文本大小,将文本大小信息存放在rect中
 val textWidth = measureText(temp)
 val textMetrics = fontMetrics

 

 

接下来是重点研究渲染器

渲染器分为:

1.线性渲染,LinearGradient

2.环形渲染 RadialGradient

3.扫描渲染 RadialGradient

4.位图渲染 BitmapShader

5.组合渲染  ComposeShader

 

 

分别看下参数 和 效果

线性渲染:

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,渐变就是线性变化
title:用于指定控件区域大于指定的渐变区域是,空白区域的颜色填充方式

     
       shader= LinearGradient(0f,0f,500f,500f ,
                intArrayOf(Color.RED,Color.BLUE,Color.GREEN), floatArrayOf(0f,0.7f,1f),Shader.TileMode.REPEAT)
        paint.shader = shader
//        canvas?.drawCircle(250f,250f,250f,paint)
        canvas?.drawRect(0f,0f,1000f,1000f,paint)

效果: 因为 这个画笔设置了3个颜色.红,蓝,绿  .分别在  0, 0.7 , 1   这3个位置坐渐变,  由于起始点是0,0  也就是屏幕左上角,结束点时是 500,500, 那么  而矩形的宽高是1000*1000  所以 画笔是花不完这么大的区域 用到tileMode   这个属性,设置Shader.TileMode.REPEAT

表示如果填充不完,就重复填充也就是以500,500,为起点   结束点 是(500+500,500+500)正好1000,1000  看到效果是画笔的2次重复绘制

 

 

环形渲染

RadialGradient(float centerX, float centerY, float radius,@NonNull @ColorInt int colors[], @Nullable floatstops[],@NonNull TileMode tileMode)
 centerX centerY 辐射中心的坐标
 radius 辐射半径
 centerColor 辐射中心的颜色
 edgeColor 辐射边缘的颜色
colors 渐变颜色数组
stoops 渐变位置数组,类似扫描的positions数组 取[0,1],中心为0,半径到达位置为1.0f
 titleMode 未覆盖意外的填充颜色模式
shader= RadialGradient(250f,250f,250f,
        intArrayOf(Color.GREEN,Color.YELLOW,Color.RED),null,Shader.TileMode.CLAMP)
paint.  shader = shader
canvas?.drawCircle(250f,250f,250f,paint)

 

扫描渲染

SweepGradient(float cx, float cy, @ColorInt int color0, @ColorInt int color1) 
* @param cx       渐变中心的坐标
* @param cy       渐变中心的坐标
* @param color0   渐变开始结束颜色
* @param color1   The color to use at the end of the sweep

 

     shader= SweepGradient(250f,250f,Color.RED,Color.GREEN)
        paint.shader=shader
        canvas?.drawCircle(250f,250f,250f,paint)

圆心250,250 半径250 以红色开始 绿色结束扫描一周渐变 

 

位图渲染

BitmapShader(@NonNull Bitmap bitmap, @NonNull TileMode tileX, @NonNull TileMode tileY) 
* @param bitmap 构造BitmapShader使用的bitmap
* @param tileX 水平方向的TileMode
* @param tileY 垂直方向的TileMode
* REPEAT 绘制区域超过渲染区域的部分,重复排版
* CLAMP 绘制区域超过渲染区域的部分,重复最后一个像素拉伸排版
* MIRROR 绘制区域超过渲染区域的部分 镜像翻转排版
 private val mBitmap :Bitmap by lazy{
        BitmapFactory.decodeResource(resources, R.mipmap.test)
    }

 shader= BitmapShader(mBitmap,Shader.TileMode.MIRROR,Shader.TileMode.MIRROR)
        paint.shader=shader
        canvas?.drawCircle(250f,250f,250f,paint)
       // canvas?.drawRect(0f,0f,mBitmap.width.toFloat(),mBitmap.height.toFloat(),paint)
      //  canvas?.drawRect(0f,0f,500f,500f,paint)

 

可以看出来 图片如果水平宽度不够了, 他会水平镜像复制平铺,如果垂直方向 高度不够,会镜像赋值图片,这就是mirror属性

 

组合渲染

BitmapShader(@NonNull Bitmap bitmap, @NonNull TileMode tileX, @NonNull TileMode tileY)

         * @param shaderA  要混合的2种shader
         * @param shaderB  要混合的2种shader
         * @param PorterDuff.Mode mode     组合2中shader颜色的模式
         * @param Xfermode   mode  组合2中shader颜色的模式

val bitmapShader = BitmapShader(mBitmap,Shader.TileMode.REPEAT,Shader.TileMode.REPEAT)
val linearGradient = LinearGradient(0f,0f,500f,500f , intArrayOf(Color.RED,Color.GREEN,Color.BLUE),null,Shader.TileMode.MIRROR )
shader= ComposeShader(bitmapShader,linearGradient,PorterDuff.Mode.MULTIPLY)
paint.shader=shader
canvas?.drawCircle(250f,250f,250f,paint)
第一个是位图渲染, 用的镜像平铺,第二个是线性渲染,红绿蓝渐变.用的也是镜像,这2个渲染器组合一下,效果很帅

逐个研究18种图层混合模式

 

 //所绘制不会提交到画布上
            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)

离屏绘制

通过使用离屏缓冲吧要绘制的内容单独绘制在缓冲层,保证Xfermode的使用不会出现错误的结果.

 

Canvas.saveLayer()可以做短时的离屏缓冲,再绘制之前保存,绘制之后恢复

int saveId=canvs.saveLayer(0,0,width,height,Canvas.All_SAVE_FLAG);

Canvas.drawBitmap(rectBitmap,0,0,paint);//画方

Paint.setXfermode(xfermode);//设置Xfermode

Canvas.drawBitmap(circleBitmap,0,0,paint);//画圆

Paint.setXfermode(null);用完及时清除Xfermode

canvas.restoreToCount(saveId)

 

 

View.setLayerType()直接把整个View都绘制在离屏绘制缓冲中

setLayerType(LAYER_TYPE_HARDWARE)使用GPU来缓冲

setLayerType(LAYER_TYPE_SOFTWARE)使用一个bitmap来缓冲

 

 

LightingColorFilter滤镜
构造方法  (作用 :改变 图片RGBA的值  从而改变图片颜色)

LightingColorFilter(int mul,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



其实就是mul一般是2个16进制  范围00 ~ff  然后除以 0xff  就相当于  一个百分比  再乘上目标颜色的 值

而add就是直接加一个颜色值

用法:

class MyLightingColorFilter : View {
    private var mPaint: Paint? = null
    private var mBitmap: Bitmap? = null


    constructor(context: Context) : super(context) {
        mPaint = Paint()
        mBitmap = BitmapFactory.decodeResource(resources, R.mipmap.girl)
    }

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
    /************************************************color filter用法**********/
        //去掉红色
//        val colorFilter = LightingColorFilter(0x00ffff, 0x000000)
        //原色
//        val colorFilter = LightingColorFilter(0xffffff, 0x000000)
        //加亮绿色
//        val colorFilter = LightingColorFilter(0xffffff, 0x005500)

//        mPaint?.let {
//            it.colorFilter=colorFilter
//            canvas?.drawBitmap(mBitmap,0f,0f,it)
//        }
        /*******************************colorFilter用法 结束***************************/
        /***********************PorterDuffColorFilter用法***********************/
        /**
         * 相当于一张纯色图片 和原图的叠加  再加上 PorterDuff.Mode 模式
         * 可选模式有Darken  重叠后颜色加深
         * LIGHTEN  重叠后颜色调浅等等 具体看 PorterDuff.Mode 源码
         *
         */
//        val porterDuffColorFilter = PorterDuffColorFilter(Color.RED, PorterDuff.Mode.LIGHTEN)
//        mPaint?.let {
//            it.colorFilter=porterDuffColorFilter
//            canvas?.drawBitmap(mBitmap,100f,100f,it)
//        }
        /******************************PorterDuffColorFilter用法结束*********************************/
        /*******************colorMatrixColorFilter  用法***************************************/
       
      

//        val colorMatrix = floatArrayOf(
//            1f, 0f, 0f, 0f, 0f,//red
//            0f, 1f, 0f, 0f, 0f,//green
//            0f, 0f, 1f, 0f, 0f,//blue
//            0f, 0f, 0f, 1f, 0f//alpha
//        )
//        每一行 前4个事 RGBA的系数值   最后一个是偏移量 常见的 滤镜效果可以参考ColorFilter类中的ColorMatrix,用ColorFilterActivity打开

//      val mColorMatrixColorFilter=  ColorMatrixColorFilter(colorMatrix)
//        mPaint?.colorFilter =mColorMatrixColorFilter
//        canvas?.drawBitmap(mBitmap,100f,0f,mPaint)
        /*******************colorMatrixColorFilter  用法结束****************************/
        /*******************ColorMatrix  用法***************************************/
        val colorMatrix = ColorMatrix()
        // 亮度调节
//        colorMatrix.setScale(1f, 1f, 1f, 1f)
        //饱和度调节 0 -无色彩 1 默认 >1 饱和度加强
        colorMatrix.setSaturation(1.5f)
        //色度调节 第一个表示颜色通道  0,1,2,3  分别表示 RGBA
        //第二个参数表示要修改 的值 具体操作可以看 setRotate 的源码
        colorMatrix.setRotate(0, 45f)

        val colorMatrixColorFilter = ColorMatrixColorFilter(colorMatrix)
        mPaint?.colorFilter = colorMatrixColorFilter
        canvas?.drawBitmap(mBitmap, 100f, 0f, mPaint)
        /*******************ColorMatrix  用法结束***************************************/
    }
}

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值