Paint 顾名思义就是画笔,可以用来设置颜色、测量文字、设置图层混合模式、颜色滤镜等等。
Api中提供了两个构造方法Paint()和Paint(int flags),其中flags的值有以下几种:
/**
* int flags
* //抗锯齿标志
* public static final int ANTI_ALIAS_FLAG = 0x01;
* //使位图过滤的位掩码标志 图像在动画进行中会滤掉对Bitmap图像的优化操作,加快显示
* //速度,本设置项依赖于dither和xfermode的设置
* public static final int FILTER_BITMAP_FLAG = 0x02;
* //使位图进行有利的抖动的位掩码标志 会使绘制出来的图片颜色更加平滑和饱满,图像更加清晰
* public static final int DITHER_FLAG = 0x04;
* //下划线
* public static final int UNDERLINE_TEXT_FLAG = 0x08;
* //中划线
* public static final int STRIKE_THRU_TEXT_FLAG = 0x10;
* //加粗
* public static final int FAKE_BOLD_TEXT_FLAG = 0x20;
* //使文本平滑线性扩展的标志
* public static final int LINEAR_TEXT_FLAG = 0x40;
* //使文本的亚像素定位的绘图标志
* public static final int SUBPIXEL_TEXT_FLAG = 0x80;
* //绘制文本时允许使用位图字体的绘图标志
* public static final int EMBEDDED_BITMAP_TEXT_FLAG = 0x400;
*/
以ANTI_ALIAS_FLAG为例,调用第二个构造方法和调用paint.setAntiAlias(boolean flag);的效果是一样的。
下面看一下paint提供的其他方法
mPaint = new Paint();
//设置画笔颜色
mPaint.setColor(Color.RED);
//设置字体大小
mPaint.setTextSize(20);
//设置描边效果 FILL填充 STROKE描边 FILL_AND_STROKE填充+描边
mPaint.setStyle(Paint.Style.STROKE);
//设置描边宽度
mPaint.setStrokeWidth(15);
//设置图层混合模式,18种
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
//设置字体风格,加粗、倾斜等
mPaint.setTypeface(Typeface.SANS_SERIF);
//设置下划线
mPaint.setUnderlineText(true);
//设置删除线,即setFlags(STRIKE_THRU_TEXT_FLAG)
mPaint.setStrikeThruText(true);
//设置倾斜弧度
mPaint.setTextSkewX(2);
//设置文字X方向缩放值
mPaint.setTextScaleX(0.7f);
//设置文字对齐方式
mPaint.setTextAlign(Paint.Align.CENTER);
//设置画笔图形样式,如圆形ROUND或者方形SQUARE
mPaint.setStrokeCap(Paint.Cap.ROUND);
//设置图像抖动处理
mPaint.setDither(true);
//设置颜色过滤器
mPaint.setColorFilter(new ColorMatrixColorFilter((float[]) null));
//设置抗锯齿
mPaint.setAntiAlias(true);
//设置透明度,取值范围[0..255]
mPaint.setAlpha(0);
//设置颜色值及透明度,参数取值范围[0..255]
mPaint.setARGB(0,0,0,0);
//模拟实现粗体文字
mPaint.setFakeBoldText(true);
//在动画进行中会滤掉对Bitmap图像的优化操作,加快显示速度,本设置项依赖于dither和xfermode的设置
mPaint.setFilterBitmap(true);
//设置画笔遮罩滤镜
mPaint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.SOLID));
//设置渲染器 线性渲染LinearGradient,环形渲染SweepGradient ,扫描渲染RadialGradient,位图渲染BitmapShader
mPaint.setShader(new LinearGradient(0,0,250,250,new int[]{Color.BLUE,Color.GREEN},new float[]{0.6f,1f}, Shader.TileMode.CLAMP));
//设置图形的结合方式
mPaint.setStrokeJoin(Paint.Join.ROUND);
//测量文本大小,并存储在Rect对象中
mPaint.getTextBounds(str,0,str.length(),new Rect());
//获取文本的宽
mPaint.measureText(str);
//获取字体度量对象
mPaint.getFontMetrics();
mPaint.setStrokeCap(Paint.Cap.ROUND),该方法传递的参数包括ROUND圆角类型,SQUARE方形,BUTT默认类型,表示在末端添加一小段圆角或者方形,以画线为例。
mPaint.setStrokeCap(Paint.Cap.BUTT);
canvas.drawLine(100,100,600,100,mPaint);
mPaint.setStrokeCap(Paint.Cap.ROUND);
canvas.drawLine(100,300,600,300,mPaint);
mPaint.setStrokeCap(Paint.Cap.SQUARE);
canvas.drawLine(100,500,600,500,mPaint);
这里画了3条直线,并分别设置了相应的StrokeCap值,看一下效果
第一条直线是默认类型也就是BUTT类型,第二条是ROUND类型,第三条是SQUARE类型,我们发现,第二条直线末端添加了一小段圆角,第三条直线添加了一小段方形。
下面看一下渲染器 mPaint.setShader(Shader shader)方法,系统主要提供了四种渲染方式:线性渲染LinearGradient,环形渲染SweepGradient ,扫描渲染RadialGradient,位图渲染BitmapShader,除此以外还有一种组合渲染ComposeShader。
以LinearGradient为例,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[]表示渲染颜色所占比(positions[]的长度与colors[]必须保持一致)。TileMode 渲染模式(CLAMP,REPEAT,MIRROR)
mPaint.setShader(new LinearGradient(0,0,250,250,new int[]{Color.BLUE,Color.GREEN},new float[]{0.6f,1f}, Shader.TileMode.CLAMP));
canvas.drawRect(50, 50, 250, 250, mPaint);
mPaint.setShader(new LinearGradient(0,0,500,500,new int[]{Color.BLUE,Color.GREEN},null, Shader.TileMode.CLAMP));
canvas.drawRect(50, 300, 250, 500, mPaint);
在第一张图中,明显蓝色与绿色的占比不同,在代码中我们设置了new float[]{0.6f,1f}这样的参数,它表示Color.BLUE颜色占比至60%,60%至100%(开区间) 是Color.BLUE,Color.GREEN两者的渐变,100% 是Color.GREEN。
第二张图则没有设置该参数,是默认渲染效果。
在位图渲染中,也就是BitmapShader,构造方法
public BitmapShader(@NonNull Bitmap bitmap, @NonNull TileMode tileX, @NonNull TileMode tileY) {
this(bitmap, tileX.nativeInt, tileY.nativeInt);
}
bitmap表示即将渲染的位图,tileX 表示X方向的渲染模式,tileY 表示Y方向的渲染模式,TileMode包含三种模式CLAMP,REPEAT,MIRROR。
TileMode.CLAMP模式 表示如果绘制部分超出渲染区域,那么会拉伸最后一个像素来填充超出部分
canvas.drawBitmap(resultBitmap,0,400,mPaint);
Shader mShader = new BitmapShader(resultBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mPaint.setShader(mShader);
canvas.drawRect(0, 0, 300, 300, mPaint);
效果如下图
TileMode.REPEAT模式 如果绘制部分超出渲染区域,那么会重复排版直至填充完超出部分
TileMode.MIRRO模式 如果绘制部分超出渲染区域,X方向上下翻转,Y方向左右翻转直至填充完超出部分
这里我们将设置X方向为REPEAT,Y方向为MIRRO
Shader mShader = new BitmapShader(resultBitmap, Shader.TileMode.REPEAT, Shader.TileMode.MIRROR);
mPaint.setShader(mShader);
canvas.drawRect(0, 0, 300, 300, mPaint);
可以很明显的观察到水平方向是重复绘制,垂直方向是镜像绘制。
再看一下ComposeShader 组合渲染,构造方法
public ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB,
@NonNull PorterDuff.Mode mode) {
this(shaderA, shaderB, mode.nativeInt);
}
public ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, @NonNull Xfermode mode) {
this(shaderA, shaderB, mode.porterDuffMode);
}
参数说明
shaderA,shaderB:要混合的两种shader
Xfermode mode: 组合两种shader颜色的模式
PorterDuff.Mode mode: 组合两种shader颜色的模式
BitmapShader bitmapShader = new BitmapShader(resultBitmap, 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);
Shader mShader = new ComposeShader(bitmapShader, linearGradient, PorterDuff.Mode.MULTIPLY);
mPaint.setShader(mShader);
canvas.drawCircle(250, 250, 250, mPaint);
这里采用了位图渲染+线性渲染的组合渲染模式,看一下效果
最后再来看一下 mPaint.getFontMetrics(); 字体度量对象FontMetrics,api中提供了以下几个变量
/**
* 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;