淘先锋技术网

首页 1 2 3 4 5 6 7

概念:

画笔,保存了绘制几何图形,文本和位图的样式和颜色信息。

常用API:

常用API主要如颜色效果和文本相关等。

当我们调用常用API的时候直接调用native方法。

初始化

 mPaint = new Paint(); //初始化
 mPaint.setAntiAlias(true); // 抗锯齿

描边效果

mPaint.setStyle(Paint.Style.FILL); //描边效果

setStyle里面有三种属性


    public enum Style {
      
        FILL            (0),
        
        STROKE          (1),
       
        FILL_AND_STROKE (2);

       ...
    }
FILL属性:

在这里插入图片描述

STROKE属性:

在这里插入图片描述

FILL_AND_STROKE

两种同时作用


描边宽度


 mPaint.setStrokeWidth(4);//描边宽度

上图中圆环的宽度

圆角效果

   mPaint.setStrokeCap(Paint.Cap.ROUND); //圆角效果

Paint.Cap.ROUND里面有三种属性

    public enum Cap {
       
        BUTT    (0),
     
        ROUND   (1),
       
        SQUARE  (2);

        private Cap(int nativeInt) {
            this.nativeInt = nativeInt;
        }
        final int nativeInt;
    }

如果是画直线

        mPaint = new Paint(); //初始化

        mPaint.setStrokeWidth(44);//描边宽度
        mPaint.setStrokeCap(Paint.Cap.ROUND); //圆角效果
            @Override
            
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            canvas.drawLine(400,400,600,400,mPaint);
        }

拐角风格

setStrokeJoin(Paint.Join join)

设置线段连接处样式,取值有:Join.MITER(结合处为锐角)、Join.Round(结合处为圆弧)、Join.BEVEL(结合处为直线)
在这里插入图片描述

设置环形渲染器

mPaint.setShader(new SweepGradient(200, 200, Color.BLUE, Color.RED)); //设置环形渲染器

设置图层混合模式

 mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DARKEN)); //设置图层混合模式

设置颜色过滤器

mPaint.setColorFilter(new LightingColorFilter(0x00ffff, 0x000000)); //设置颜色过滤器 光照效果

设置双线性过滤

mPaint.setFilterBitmap(true); //设置双线性过滤 将图片过度平滑

在这里插入图片描述

设置画笔遮罩滤镜 ,传入度数和样式

mPaint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.NORMAL));//设置画笔遮罩滤镜 ,传入度数和样式

设置文本缩放倍数

mPaint.setTextScaleX(2);// 设置文本缩放倍数

设置字体大小

//        mPaint.setTextSize(38);// 设置字体大小


对其方式

//        mPaint.setTextAlign(Paint.Align.LEFT);//对其方式

设置下划线

//        mPaint.setUnderlineText(true);// 设置下划线

文本大小宽度字体度量

//        String str = "Android";
//        Rect rect = new Rect();
//        mPaint.getTextBounds(str, 0, str.length(), rect); //测量文本大小,将文本大小信息存放在rect中
//        mPaint.measureText(str); //获取文本的宽
//        mPaint.getFontMetrics(); //获取字体度量对象

对于指定字号的某种字体,再度量方面的各种属性。参数包括:

  • baseline:字符基线
  • ascent:字符最高点到baseline的推荐距离
  • top:字符最高点到baseline的最大距离
  • descent:字符最低点到baseline的推荐距离
  • bottom:字符最低点到baseline的最大距离
  • leading:行间距,即前一行的descent与下一行的ascent之间的距离
    在这里插入图片描述
    右键图片另存为,查看大图

Paint颜色相关

  1. setcolor( int color)参数具体的颜色值,16 进制数值,0XFFF000
  2. . setARGB(inta,intr,intg,intb)参数分别透明度,红,绿,蓝。0-255 数值
  3. shader( Shadershader)参数着色器对象,一般使用 shader 的几个子类
  • Lineargradient:线性渲染
  • RadialGradient:环形渲染
  • SweepGradient:扫描渲染
  • BitmapShader:位图渲染
  • ComposeShader:组合渲染,例如 LinearGradient+ Bitmap shader
  1. setColorFilter( Colorfilter colorfilter)设置颜色过滤。一般使用

Colorfilter 三个子类:

  • Lighting ColorFilter:光照效果
  • PorterDuffcolorfilter:指定一个颜色和一种 PorterDuff Mode 与绘制对象进行合成
  • ColorMatrixcolorfilter:使用一个 ColorMatrix 来对颜色进行处理
LinearGradients线性渲染
public LinearGradient (float x0, 
                float y0, 
                float x1, 
                float y1, 
                long[] colors, 
                float[] positions, 
                Shader.TileMode tile)
参数
x0 yo x1 y1渐变的两个端点的位置
color0 color1是端点的颜色
tile端点范围之外的着色规则,类型是 TileMode
使用:
    /**
     * 线性渲染,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,渐变就线性变化。
     * tile:用于指定控件区域大于指定的渐变区域时,空白区域的颜色填充方法
     */
    mShader = new LinearGradient(0, 0, 500, 500, new int[]{Color.RED, Color.BLUE, Color.GREEN}, new float[]{0.f,0.7f,1}, Shader.TileMode.REPEAT);
    mPaint.setShader(mShader);
 	canvas.drawCircle(250, 250, 250, mPaint);
效果

在这里插入图片描述

注意:

红到蓝渐变

new int[]{Color.RED, Color.BLUE, Color.GREEN}, new float[]{0.f,0.7f,1}
个数是相对应的
color.red和0.f对应
Color.BLUE和0.7f对应
Color.GREEN和1对应
RadialGradient环形渲染
public RadialGradient (float centerX, float centerY, float radius, int centerColor, int edgeColor, Shader.TileMode tileMode)
参数
centerX centerY辐射中心的坐标
radius辐射半径
centerColor辐射中心的颜色
tileMode辐射范围之外的着色规则,类型是 TileMode
使用:
    /**
     * 环形渲染,RadialGradient(float centerX, float centerY, float radius, @ColorInt int colors[], @Nullable float stops[], TileMode tileMode)
     * centerX ,centerY:shader的中心坐标,开始渐变的坐标
     * radius:渐变的半径
     * centerColor,edgeColor:中心点渐变颜色,边界的渐变颜色
     * colors:渐变颜色数组
     * stoops:渐变位置数组,类似扫描渐变的positions数组,取值[0,1],中心点为0,半径到达位置为1.0f
     * tileMode:shader未覆盖以外的填充模式。
     */
    mShader = new RadialGradient(250, 250, 250, new int[]{Color.GREEN, Color.YELLOW, Color.RED}, null, Shader.TileMode.CLAMP);
    mPaint.setShader(mShader);
    canvas.drawCircle(250, 250, 250, mPaint);
效果

在这里插入图片描述

SweepGradient 扫描渲染
public SweepGradient (float cx, float cy, int color0, int color1)
参数
cx cy扫描的中心
color0扫描的起始颜色
color1扫描的终止颜色
使用:
     /**
     * 扫描渲染,SweepGradient(float cx, float cy, @ColorInt int color0,int color1)
     * cx,cy 渐变中心坐标
     * color0,color1:渐变开始结束颜色
     * colors,positions:类似LinearGradient,用于多颜色渐变,positions为null时,根据颜色线性渐变
     */
    mShader = new SweepGradient(250, 250, Color.RED, Color.GREEN);
    mPaint.setShader(mShader);
    canvas.drawCircle(250, 250, 250, mPaint);
效果

在这里插入图片描述

位图渲染
public BitmapShader (Bitmap bitmap, Shader.TileMode tileX, Shader.TileMode tileY)
参数
bitmap用来做模板的 Bitmap对象
tileX横向的着色规则 ,类型是TileMode
tileY纵向的着色规则 ,类型是TileMode
使用:
     /**
     * 位图渲染,BitmapShader(@NonNull Bitmap bitmap, @NonNull TileMode tileX, @NonNull TileMode tileY)
     * Bitmap:构造shader使用的bitmap
     * tileX:X轴方向的TileMode
     * tileY:Y轴方向的TileMode
     * REPEAT, 绘制区域超过渲染区域的部分,重复排版
     *   CLAMP, 绘制区域超过渲染区域的部分,会以最后一个像素拉伸排版
     *  MIRROR, 绘制区域超过渲染区域的部分,镜像翻转排版
     */
    mShader = new BitmapShader(mBitmap, Shader.TileMode.REPEAT, Shader.TileMode.MIRROR);
    mPaint.setShader(mShader);
    canvas.drawRect(0,0,500, 500, mPaint);

在这里插入图片描述镜像是因为MIRROR
重复是因为REPEAT
还有一个CLAMP,将图片最后一个拉伸

如果改成横轴改成 CLAMP

        mShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.MIRROR);
        mPaint.setShader(mShader);
        canvas.drawRect(0,0,500, 500, mPaint);

在这里插入图片描述

组合渲染
public ComposeShader (Shader shaderA, Shader shaderB, PorterDuff.Mode mode)
参数
shaderA shaderB两个相继使用的 Shader
mode两个Sharder的叠加模式,ShaderA 和 shaderB应该怎样共同绘制。它的类型是PorterDuff.Mode
        /**
         * 组合渲染,
         * ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, Xfermode mode)
         * ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, PorterDuff.Mode mode)
         * shaderA,shaderB:要混合的两种shader
         * Xfermode mode: 组合两种shader颜色的模式
         * PorterDuff.Mode mode: 组合两种shader颜色的模式
         */
        BitmapShader bitmapShader = new BitmapShader(mBitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
        LinearGradient linearGradient = new LinearGradient(0, 0, 1000, 1600, new int[]{Color.RED, Color.GREEN, Color.BLUE}, null, Shader.TileMode.CLAMP);
        mShader = new ComposeShader(bitmapShader, linearGradient, PorterDuff.Mode.MULTIPLY);
        mPaint.setShader(mShader);
        canvas.drawCircle(250, 250, 250, mPaint);

在这里插入图片描述

Shader.TileMode着色模式

ShaderTileMode着色模式
Shader.TileMode.CLAMP 超出的部分以最后一个像素来排版
Shader.TileMode.MIRROR 超出的部分以镜像翻转来排版
Shader.TileMode.REPEAT 超出的部分重复排版
使用:

        mShader = new BitmapShader(mBitmap, Shader.TileMode.REPEAT, Shader.TileMode.MIRROR);
        mPaint.setShader(mShader);
        canvas.drawRect(0,0,500, 500, mPaint);
PorterDuff.Mode图层混合模式

它将所绘制图形的像素与Canvas中对应位置的像素按照一定规则进行混合,形成新的像素值,从而更新 Canvas中最终的像素颜色值

18种模式

public class PorterDuff {
    public PorterDuff() {
        throw new RuntimeException("Stub!");
    }

    public static enum Mode {
        ADD,
        CLEAR,
        DARKEN,
        DST,
        DST_ATOP,
        DST_IN,
        DST_OUT,
        DST_OVER,
        LIGHTEN,
        MULTIPLY,
        OVERLAY,
        SCREEN,
        SRC,
        SRC_ATOP,
        SRC_IN,
        SRC_OUT,
        SRC_OVER,
        XOR;

        private Mode() {
        }
    }
}

三个使用的地方

        //1.ComposeShader
        //2.画笔Paint.setXfermode()
        //3.PorterDuffColorFilter

首先禁止硬件加速

 //禁止硬件加速
 setLayerType(View.LAYER_TYPE_SOFTWARE, null);

谷歌提供APIDemos教我们如何使用

https://github.com/THEONE10211024/ApiDemos

找到
XfermodesActivity

离屏绘制

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

使用离屏缓冲有两种方式

第一种

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

第二种

View.setLayerType()直接把整个View都绘制在离屏缓冲中。
setLayerType(LAYER_TYPE_ HARDWARE)使用GPU来缓冲,
setLayerType(LAYER_TYPE_SOFTWARE)使用一个 Bitmap来缓冲

先看第一种:

public class XfermodeView extends View {

    private Paint mPaint;
    private int mWidth, mHeight;

    public XfermodeView(Context context) {
        this(context, null);
    }

    public XfermodeView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public XfermodeView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }


    private void init() {
        //初始化画笔
        mPaint = new Paint();
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = MeasureSpec.getSize(widthMeasureSpec);
        mHeight = MeasureSpec.getSize(heightMeasureSpec);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //1.ComposeShader
        //2.画笔Paint.setXfermode()
        //3.PorterDuffColorFilter

        //禁止硬件加速
        setLayerType(View.LAYER_TYPE_SOFTWARE, null);

        setBackgroundColor(Color.GRAY);

        //离屏绘制
        int layerId = canvas.saveLayer(0,0, getWidth(), getHeight(), mPaint, Canvas.ALL_SAVE_FLAG);

        //目标图
        canvas.drawBitmap(createRectBitmap(mWidth, mHeight), 0, 0, mPaint);
        //设置混合模式
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        //源图,重叠区域右下角部分
        canvas.drawBitmap(createCircleBitmap(mWidth, mHeight), 0, 0, mPaint);
        //清除混合模式
        mPaint.setXfermode(null);

        canvas.restoreToCount(layerId);

    }

    //画矩形Dst
    public Bitmap createRectBitmap(int width, int height) {
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        Paint dstPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        dstPaint.setColor(0xFF66AAFF);
        canvas.drawRect(new Rect(width / 20, height / 3, 2 * width / 3, 19 * height / 20), dstPaint);
        return bitmap;
    }

    //画圆src
    public Bitmap createCircleBitmap(int width, int height) {
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        Paint scrPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        scrPaint.setColor(0xFFFFCC44);
        canvas.drawCircle(width * 2 / 3, height / 3, height / 4, scrPaint);
        return bitmap;
    }


}

效果

在这里插入图片描述如果去掉离屏绘制,将如下代码注释掉

 //离屏绘制
        int layerId = canvas.saveLayer(0,0, getWidth(), getHeight(), mPaint, Canvas.ALL_SAVE_FLAG);
  canvas.restoreToCount(layerId);

则效果
在这里插入图片描述

注意

添加离屏绘制,是先将矩形和圆合成一个图形,然后绘制到canvas中,再添加背景 setBackgroundColor(Color.GRAY);

而不添加离屏绘制,是将背景和矩形以及圆都绘制到canvas中。导致合成的图有灰色的背景。

也就是说离屏绘制是像图层一样,先后摆放绘制。

具体小案例

hongyang的博客 刮刮卡效果

pain效果相关 滤镜

LightingColorFilter光照效果滤镜
public LightingColorFilter (int mul, int add)

mul和add都是和颜色值格式相同的int值,其中mul用来和目标像素相乘,add用来和目标像素相加:
alpha通道将被忽略.

如果 mul 为 0xffffff,add 为 0x000000则为原图

R' = R * mul.R / 0xff + add.R
G' = G * mul.G / 0xff + add.G
B' = B * mul.B / 0xff + add.B

R G B目标
R' 得到后的结果

使用:

        /**
         * R' = R * mul.R / 0xff + add.R 00
         * G' = G * mul.G / 0xff + add.G ff
         * B' = B * mul.B / 0xff + add.B ff
         */
        //红色去除掉
        LightingColorFilter lighting = new   LightingColorFilter(0x00ffff,0x000000);
        mPaint.setColorFilter(lighting);
        canvas.drawBitmap(mBitmap, 0,0, mPaint);

在这里插入图片描述

PorterDuffColorFilter滤镜

使用一个指定的颜色和一种指定的 PorterDuff.Mode 来与绘制对象进行合成.

public PorterDuffColorFilter (int color, PorterDuff.Mode mode)
参数
color具体的颜色值
mode指定PorterDuff.Mode混合模式
        PorterDuffColorFilter porterDuffColorFilter = new PorterDuffColorFilter(Color.RED, PorterDuff.Mode.DARKEN);
        mPaint.setColorFilter(porterDuffColorFilter);
        canvas.drawBitmap(mBitmap, 100, 0, mPaint);
ColorMatrixColorFilter
public ColorMatrixColorFilter (float[] array)
参数
array4*5列矩阵数组
使用
        float[] colorMatrix = {
                1,0,0,0,0,   //red
                0,1,0,0,0,   //green
                0,0,1,0,0,   //blue
                0,0,0,1,0    //alpha
        };
        mColorMatrixColorFilter = new ColorMatrixColorFilter(colorMatrix);
        mPaint.setColorFilter(mColorMatrixColorFilter);
        canvas.drawBitmap(mBitmap, 100, 0, mPaint);
        ColorMatrix cm = new ColorMatrix();
        //亮度调节,调节初始矩阵进行重新赋值
        cm.setScale(1,2,1,1);
//
        //饱和度调节0-无色彩, 1- 默认效果, >1饱和度加强
//        cm.setSaturation(2);
//
//        //色调调节
//        cm.setRotate(0, 45);
//
        mColorMatrixColorFilter = new ColorMatrixColorFilter(cm);
        mPaint.setColorFilter(mColorMatrixColorFilter);
        canvas.drawBitmap(mBitmap, 100, 0, mPaint);

参考:
https://hencoder.com/ui-1-2/

部分内容参考于网络,无法找到原创标记。如果是你原创,请联系我添加。