零、前言:
1.曾经也算半个艺术家,深知笔的重要性与复杂性
2.Android里的Paint设置项好多基本上都是setXXX,getXXX,很多文字相关的内容都在Paint里
3.主要由画笔常规配置,画笔类型、画笔特效(线效,着色,滤色)、画笔文字
4.本文暂时还无法覆盖Paint的所有API,能用的吾尽量都会涉及一下
最主要的还是set方法
paint的Set一览.png一、画笔的常规配置
public void setColor(@ColorInt int color) //设置颜色
public void setAlpha(int a)//设置透明度
public void setARGB(int a, int r, int g, int b)//设置ARGB颜色
public void setStrokeWidth(float width)//设置宽度
public void setAntiAlias(boolean aa)//设置抗锯齿
基本设置.png
二、笔的样式:Paint.Style.
:[#FILL
|STROKE
|FILL_AND_STROKE
]
/**
* 样式测试
* @param canvas
*/
private void testStyle(Canvas canvas) {
Rect rect = new Rect(0, 0, 100, 100);
mRedPaint.setStrokeWidth(15);
canvas.save();
mRedPaint.setStyle(Paint.Style.FILL);
canvas.translate(50, 450);
canvas.drawRect(rect, mRedPaint);
canvas.translate(150, 0);
mRedPaint.setStyle(Paint.Style.STROKE);
canvas.drawRect(rect, mRedPaint);
canvas.translate(150 , 0);
mRedPaint.setStyle(Paint.Style.FILL_AND_STROKE);
canvas.drawRect(rect, mRedPaint);
canvas.restore();
mRedPaint.setStrokeWidth(40);
}
画笔样式测试.png
三、线帽:Paint.Cap.
:[#BUTT
|ROUND
|SQUARE
]
1.绘制圆形的点:Paint.Cap.ROUND
/**
* 绘制圆形的点
*
* @param canvas
*/
private void drawPos(Canvas canvas) {
//设置画笔圆帽
mRedPaint.setStrokeCap(Paint.Cap.ROUND);
mRedPaint.setStrokeWidth(20);
//绘制点
canvas.drawPoint(100, 100, mRedPaint);
canvas.drawPoints(new float[]{
400, 400, 500, 500,
600, 400, 700, 350,
800, 300, 900, 300
}, mRedPaint);
}
绘制圆点.png
2.三种线帽比较
/**
* 线帽型状测试:Paint.Cap.BUTT、Paint.Cap.ROUND、Paint.Cap.SQUARE
*
* @param canvas
*/
private void testOfCap(Canvas canvas) {
canvas.save();
canvas.translate(150, 200);
//线帽测试:
mRedPaint.setStrokeCap(Paint.Cap.BUTT);//无头(默认)
canvas.drawLine(0, 0, 0, 200, mRedPaint);
canvas.translate(50, 0);
mRedPaint.setStrokeCap(Paint.Cap.ROUND);//圆头
canvas.drawLine(0, 0, 0, 200, mRedPaint);
canvas.translate(50, 0);
mRedPaint.setStrokeCap(Paint.Cap.SQUARE);//方头
canvas.drawLine(0, 0, 0, 200, mRedPaint);
canvas.restore();
}
线帽型状测试.png
四、线交角测试:Paint.Join.
:[#BEVEL
|ROUND
|MITER
]
注意:只有路径绘制的线才有交角效果
/**
* 角型测试:Paint.Join.BEVEL、Paint.Join.ROUND、Paint.Join.MITER
*
* @param canvas
*/
private void testOfJoin(Canvas canvas) {
mRedPaint.setStyle(Paint.Style.STROKE);
mRedPaint.setStrokeWidth(40);
Path path = new Path();
path.moveTo(30, 0);
path.lineTo(0, 100);
path.lineTo(100, 100);
canvas.save();
canvas.translate(600, 100);
mRedPaint.setStrokeJoin(Paint.Join.BEVEL);//直线(默认)
canvas.drawPath(path, mRedPaint);
canvas.translate(150, 0);
mRedPaint.setStrokeJoin(Paint.Join.ROUND);//圆角
canvas.drawPath(path, mRedPaint);
canvas.translate(150, 0);
mRedPaint.setStrokeJoin(Paint.Join.MITER);//锐角
canvas.drawPath(path, mRedPaint);
canvas.restore();
}
线交角测试.png
五、Paint的路径效果
1.虚线:DashPathEffect(new float[]{a, b, a1, b1...}, offSet)
虚线效果.gif第一参为显隐线段的长度,第二参为偏移值
下面会动的线是不断改变偏移量:mDashOffSet的结果
/**
* 虚线测试
*
* @param canvas
*/
private void dashEffect(Canvas canvas) {
mEffectPaint = new Paint(mRedPaint);
mEffectPaint.setStrokeCap(Paint.Cap.BUTT);
//显示100,隐藏50,显示50,隐藏50,的循环
mEffectPaint.setPathEffect(new DashPathEffect(new float[]{100, 50, 50, 50}, 0));
Path path = new Path();
path.moveTo(100, 650);
path.lineTo(1000, 650);
canvas.drawPath(path, mEffectPaint);
//显示100,隐藏50,显示60,隐藏50,的循环,偏移:mDashOffSet
mEffectPaint.setPathEffect(new DashPathEffect(new float[]{100, 50, 50, 50}, mDashOffSet));
Path pathOffset50 = new Path();
pathOffset50.moveTo(100, 750);
pathOffset50.lineTo(1000, 750);
canvas.drawPath(pathOffset50, mEffectPaint);
}
2.折角弧:CornerPathEffect(corner)
折角弧.gif动画是不断改变圆角大小:mEffectCorner的结果
/**
* 圆角折线
*
* @param canvas
*/
private void cornerEffect(Canvas canvas) {
mEffectPaint.setPathEffect(new CornerPathEffect(mEffectCorner));
mEffectPaint.setStyle(Paint.Style.STROKE);
mEffectPaint.setStrokeWidth(40);
Path path = new Path();
path.moveTo(550, 550);
path.lineTo(900, 300);
path.lineTo(1000, 550);
canvas.drawPath(path, mEffectPaint);
//蓝色辅助线
Paint tempPaint = new Paint();
tempPaint.setStyle(Paint.Style.STROKE);
tempPaint.setColor(Color.BLUE);
tempPaint.setStrokeWidth(2);
tempPaint.setPathEffect(new DashPathEffect(new float[]{20, 20}, 0));
Path helpPath = new Path();
helpPath.moveTo(550, 550);
helpPath.lineTo(900, 300);
helpPath.lineTo(1000, 550);
canvas.drawPath(helpPath, tempPaint);
}
3.离散路径:DiscretePathEffect(小段长,偏移量)
离散路径.png/**
* 离散路径
*
* @param canvas
*/
private void discreteEffect(Canvas canvas) {
canvas.save();//保存画布状态
canvas.translate(0, 950);
//第一个参数:将原来的路径切成多长的线段,越小,所切成的小线段越多
//第二参数:被切成的每个小线段的可偏移距离。越大,每个线段的可偏移距离就越大。
Path path = new Path();
// 定义路径的起点
path.moveTo(100, 0);
path.lineTo(600, -100);
path.lineTo(1000, 0);
mEffectPaint.setPathEffect(new DiscretePathEffect(2, 5));
mEffectPaint.setStrokeWidth(2);
canvas.drawPath(path, mEffectPaint);
canvas.translate(0, 100);
mEffectPaint.setPathEffect(new DiscretePathEffect(20, 5));
canvas.drawPath(path, mEffectPaint);
canvas.restore();//重新储存画布状态
}
4.路径点样:PathDashPathEffect(路径,间距,偏移,样式)
路径样点.gif通过动图可以很清楚得看出三个样式的区别
动图是不断改变偏移量:mDashOffSet的结果
//Path shape:表示[路径点样],这里是一个五角星
//float advance:表示两个[路径点样]间的距离
//float phase:路径绘制偏移距离
//Style style:表示在遇到转角时的过渡样式
// ----Style.ROTATE表示通过旋转[路径点样]来过渡转角;
// ----Style.MORPH表示通过变形[路径点样]来过渡转角;
// ----Style.TRANSLATE表示通过位移[路径点样]来过渡转角。
/**
* 路径点样路径样式
*
* @param canvas
*/
private void PathDashEffect(Canvas canvas) {
canvas.save();
canvas.translate(0, 1100);
Path path = new Path();
// 定义路径的起点
path.moveTo(100, 80);
path.lineTo(600, -100);
path.lineTo(1000, 80);
//变形过渡
mEffectPaint.setPathEffect(new PathDashPathEffect(
CommonPath.nStarPath(5, 16, 8), 40, mDashOffSet, PathDashPathEffect.Style.ROTATE));
canvas.drawPath(path, mEffectPaint);
canvas.restore();
//旋转过渡
canvas.save();
canvas.translate(0, 1200);
mEffectPaint.setPathEffect(new PathDashPathEffect(
CommonPath.nStarPath(5, 16, 8), 40, mDashOffSet, PathDashPathEffect.Style.MORPH));
canvas.drawPath(path, mEffectPaint);
canvas.restore();
//移动过渡
canvas.save();
canvas.translate(0, 1300);
mEffectPaint.setPathEffect(new PathDashPathEffect(
CommonPath.nStarPath(5, 16, 8), 40, mDashOffSet, PathDashPathEffect.Style.TRANSLATE));
canvas.drawPath(path, mEffectPaint);
canvas.restore();
}
/**
* 离散路径
*
* @param canvas
*/
private void discreteEffect(Canvas canvas) {
canvas.save();//保存画布状态
canvas.translate(0, 950);
//第一个参数:将原来的路径切成多长的线段,越小,所切成的小线段越多
//第二参数:被切成的每个小线段的可偏移距离。越大,每个线段的可偏移距离就越大。
Path path = new Path();
// 定义路径的起点
path.moveTo(100, 0);
path.lineTo(600, -100);
path.lineTo(1000, 0);
mEffectPaint.setPathEffect(new DiscretePathEffect(2, 5));
mEffectPaint.setStrokeWidth(2);
canvas.drawPath(path, mEffectPaint);
canvas.translate(0, 100);
mEffectPaint.setPathEffect(new DiscretePathEffect(20, 5));
canvas.drawPath(path, mEffectPaint);
canvas.restore();//重新储存画布状态
}
n角星路径封装:
/**
* n角星路径
*
* @param num 几角星
* @param R 外接圆半径
* @param r 内接圆半径
* @return n角星路径
*/
public static Path nStarPath(int num, float R, float r) {
Path path = new Path();
float perDeg = 360 / num;
float degA = perDeg / 2 / 2;
float degB = 360 / (num - 1) / 2 - degA / 2 + degA;
path.moveTo(
(float) (Math.cos(rad(degA + perDeg * 0)) * R + R * Math.cos(rad(degA))),
(float) (-Math.sin(rad(degA + perDeg * 0)) * R + R));
for (int i = 0; i < num; i++) {
path.lineTo(
(float) (Math.cos(rad(degA + perDeg * i)) * R + R * Math.cos(rad(degA))),
(float) (-Math.sin(rad(degA + perDeg * i)) * R + R));
path.lineTo(
(float) (Math.cos(rad(degB + perDeg * i)) * r + R * Math.cos(rad(degA))),
(float) (-Math.sin(rad(degB + perDeg * i)) * r + R));
}
path.close();
return path;
}
/**
* 角度制化为弧度制
*
* @param deg 角度
* @return 弧度
*/
public static float rad(float deg) {
return (float) (deg * Math.PI / 180);
}
5.叠加特效:PathDashPathEffect(e1,e2...)(此处演示:离散效果+样点效果)
特效叠加.gif/**
* 叠加样式
*
* @param canvas
*/
private void composeEffect(Canvas canvas) {
mEffectPaint.setStyle(Paint.Style.STROKE);
mEffectPaint.setStrokeWidth(40);
canvas.save();
canvas.translate(0, 1400);
Path path = new Path();
// 定义路径的起点
path.moveTo(100, 80);
path.lineTo(600, -100);
path.lineTo(1000, 80);
PathDashPathEffect effect1 = new PathDashPathEffect(
CommonPath.nStarPath(5, 16, 8), 40, mDashOffSet, PathDashPathEffect.Style.ROTATE);
DiscretePathEffect effect2 = new DiscretePathEffect(20, 5);
mEffectPaint.setPathEffect(new ComposePathEffect(effect1, effect2));//离散效果+样点效果
canvas.drawPath(path, mEffectPaint);
canvas.restore();
}
6.路径叠加
路径叠加.gif/**
* 路径叠加
*
* @param canvas
*/
private void sumEffect(Canvas canvas) {
canvas.save();
canvas.translate(0, 1500);
Path path = new Path();
// 定义路径的起点
path.moveTo(100, 80);
path.lineTo(600, -100);
path.lineTo(1000, 80);
PathDashPathEffect effect1 = new PathDashPathEffect(
CommonPath.nStarPath(5, 16, 8), 40, mDashOffSet, PathDashPathEffect.Style.ROTATE);
DiscretePathEffect effect2 = new DiscretePathEffect(20, 5);
mEffectPaint.setPathEffect(new SumPathEffect(effect1, effect2));//离散效果+样点效果
canvas.drawPath(path, mEffectPaint);
canvas.restore();
}
六.着色器:Shader
Shader.png一个很简单的类,有5个子类:
1.线性渐变:
1).new LinearGradient(渐变起点x,y,渐变终点x,y,渐变色1,渐变色2,渐变模式)
渐变模式:
Shader.TileMode.
[MIRROR
|CLAMP
|REPEAT
] (图中很形象,就不解释了)
int colorStart = Color.parseColor("#84F125");
int colorEnd = Color.parseColor("#5825F1");
canvas.save();
canvas.translate(mCoo.x, mCoo.y);
mRedPaint.setStyle(Paint.Style.FILL);
mRedPaint.setShader(
new LinearGradient(
-200, 0, 200, 0,
colorStart, colorEnd,
Shader.TileMode.MIRROR
));
canvas.drawRect(-400,-200,400,-100,mRedPaint);
canvas.translate(0, 150);
mRedPaint.setShader(
new LinearGradient(
-100, 0, 100, 0,
colorStart, colorEnd,
Shader.TileMode.CLAMP
));
canvas.drawRect(-400,-200,400,-100,mRedPaint);
canvas.translate(0, 150);
mRedPaint.setShader(
new LinearGradient(
-100, 0, 100, 0,
colorStart, colorEnd,
Shader.TileMode.REPEAT
));
canvas.drawRect(-400,-200,400,-100,mRedPaint);
线性渐变.png
2).多色多点渐变:LinearGradient(渐变起点x,y,渐变终点x,y,颜色数组,位置百分点数组0~1,渐变模式)
多色渐变.pngint[] colors = new int[]{
Color.parseColor("#F60C0C"),//红
Color.parseColor("#F3B913"),//橙
Color.parseColor("#E7F716"),//黄
Color.parseColor("#3DF30B"),//绿
Color.parseColor("#0DF6EF"),//青
Color.parseColor("#0829FB"),//蓝
Color.parseColor("#B709F4"),//紫
};
float[] pos = new float[]{
1.f / 7, 2.f / 7, 3.f / 7, 4.f / 7, 5.f / 7, 6.f / 7, 1
};
canvas.translate(0, 150);
mRedPaint.setShader(
new LinearGradient(
-300, 0, 300, 0,
colors, pos,
Shader.TileMode.CLAMP
));
canvas.drawRect(-400, -200, 400, -100, mRedPaint);
2.径向渐变:RadialGradient
1).两色渐变:RadialGradient(渐变中心,渐变半径,颜色1,颜色2,渐变模式)
canvas.translate(mCoo.x, mCoo.y);
int colorStart = Color.parseColor("#84F125");
int colorEnd = Color.parseColor("#5825F1");
mRedPaint.setStyle(Paint.Style.FILL);
mRedPaint.setShader(
new RadialGradient(
0,0,50,
colorStart, colorEnd,
Shader.TileMode.MIRROR
));
canvas.drawCircle(0, 0, 150, mRedPaint);
canvas.translate(350, 0);
mRedPaint.setShader(
new RadialGradient(
0,0,50,
colorStart, colorEnd,
Shader.TileMode.CLAMP
));
canvas.drawCircle(0, 0, 150, mRedPaint);
canvas.translate(350, 0);
mRedPaint.setShader(
new RadialGradient(
0,0,50,
colorStart, colorEnd,
Shader.TileMode.REPEAT
));
canvas.drawCircle(0, 0, 150, mRedPaint);
径像渐变.png
2).多色多点径向渐变:
多色径向渐变.pngRadialGradient(渐变中心,渐变半径,渐变模式,颜色数组,位置百分点数组0~1,渐变模式)
int[] colors = new int[]{
Color.parseColor("#F60C0C"),//红
Color.parseColor("#F3B913"),//橙
Color.parseColor("#E7F716"),//黄
Color.parseColor("#3DF30B"),//绿
Color.parseColor("#0DF6EF"),//青
Color.parseColor("#0829FB"),//蓝
Color.parseColor("#B709F4"),//紫
};
float[] pos = new float[]{
1.f / 7, 2.f / 7, 3.f / 7, 4.f / 7, 5.f / 7, 6.f / 7, 1
};
mRedPaint.setStyle(Paint.Style.FILL);
mRedPaint.setShader(
new RadialGradient(
0, 0, 200,
colors, pos,
Shader.TileMode.CLAMP
));
canvas.drawCircle(0, 0, 250, mRedPaint);
3.扫描渐变:SweepGradient
扫描渐变.png这个要比上面的简单一点,没有渐变的模式
双色扫描渐变:SweepGradient(中心点x,y,颜色1,颜色2)
多色扫描渐变:SweepGradient(中心点x,y,颜色数组,位置百分点数组0~1)
int colorStart = Color.parseColor("#84F125");
int colorEnd = Color.parseColor("#5825F1");
mRedPaint.setStyle(Paint.Style.FILL);
mRedPaint.setShader(
new SweepGradient(0, 0, colorStart, colorEnd));
canvas.drawCircle(0, 0, 150, mRedPaint);
canvas.translate(400, 0);
int[] colors = new int[]{
Color.parseColor("#F60C0C"),//红
Color.parseColor("#F3B913"),//橙
Color.parseColor("#E7F716"),//黄
Color.parseColor("#3DF30B"),//绿
Color.parseColor("#0DF6EF"),//青
Color.parseColor("#0829FB"),//蓝
Color.parseColor("#B709F4"),//紫
};
float[] pos = new float[]{
1.f / 7, 2.f / 7, 3.f / 7, 4.f / 7, 5.f / 7, 6.f / 7, 1
};
mRedPaint.setShader(
new SweepGradient(0, 0, colors, pos));
canvas.drawCircle(0, 0, 150, mRedPaint);
4.图片着色器:BitmapShader(图片,着色模式x,着色模式y)
用图片的所有像素点作为画笔的颜色
1).文字的图片底色:
//加载图片,生成图片着色器
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.menu_bg);
BitmapShader bs = new BitmapShader(bitmap, Shader.TileMode.CLAMP,Shader.TileMode.CLAMP);
mRedPaint.setShader(bs);
mRedPaint.setTextSize(150);
mRedPaint.setStrokeWidth(10);
mRedPaint.setStyle(Paint.Style.FILL_AND_STROKE);
canvas.drawText("张风捷特烈", 0, 500, mRedPaint);
图片着色.png
2)路径+图片着色器实现裁剪图片:路径Path相关知识见上一篇:
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.menu_bg);
BitmapShader bs = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mRedPaint.setShader(bs);
mRedPaint.setStyle(Paint.Style.FILL);
Path path = CommonPath.nStarPath(8, 500, 250);
canvas.drawPath(path, mRedPaint);
使用路径裁剪图片.png
还有一个ComposeShader比较复杂,以后有需求会专门写一篇
七、颜色过滤器:(具体原理是颜色运算,这里全当玩玩看看吧,暂不深究)
ColorFilter只有三个子类
颜色过滤器.png1.LightingColorFilter(颜色1,颜色2):
LightingColorFilter测试.png看图体会一下吧...我不说了
Bitmap mainBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.menu_bg);
mRedPaint.setStyle(Paint.Style.FILL);
mRedPaint.setColorFilter(new LightingColorFilter(
Color.parseColor("#FF0000"),//红
Color.parseColor("#0000ff")//蓝
));
canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
canvas.translate(350, 0);
mRedPaint.setColorFilter(new LightingColorFilter(
Color.parseColor("#FF0000"),//红
Color.parseColor("#00ff00")//绿
));
canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
canvas.translate(350, 0);
mRedPaint.setColorFilter(new LightingColorFilter(
Color.parseColor("#FF0000"),//红
Color.parseColor("#000000")//黑
));
canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
canvas.restore();
2.PorterDuffColorFilter(颜色,模式--PorterDuff.Mode):
PorterDuffColorFilter测试.pngPorterDuff.Mode一共17中,在Color专题会详述,这里举几个栗子看看
Bitmap mainBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.menu_bg);
mRedPaint.setStyle(Paint.Style.FILL);
mRedPaint.setColorFilter(new PorterDuffColorFilter(
Color.parseColor("#0000ff"), PorterDuff.Mode.DARKEN));
canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
canvas.translate(350, 0);
mRedPaint.setColorFilter(new PorterDuffColorFilter(
Color.parseColor("#0000ff"),PorterDuff.Mode.LIGHTEN
));
canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
canvas.translate(350, 0);
mRedPaint.setColorFilter(new PorterDuffColorFilter(
Color.parseColor("#0000ff"),PorterDuff.Mode.SCREEN
));
canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
canvas.translate(350, 0);
mRedPaint.setColorFilter(new PorterDuffColorFilter(
Color.parseColor("#0000ff"),PorterDuff.Mode.OVERLAY
));
canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
3.ColorMatrixColorFilter(颜色变换矩阵或25个float数)
颜色矩阵.png ColorMatrix.png刚好前端时间对ColorMatrix有一点研究,这里拿来用用
Bitmap mainBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.menu_bg);
mRedPaint.setStyle(Paint.Style.FILL);
//关闭RGB颜色通道(变为黑色),后偏移红色255
float[] matrix = new float[]{
-1, 0, 0, 0, 255,
0, -1, 0, 0, 0,
0, 0, -1, 0, 0,
0, 0, 0, 1, 0
};
ColorMatrix colorMatrix = new ColorMatrix(matrix);
mRedPaint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
canvas.translate(350, 0);
//关闭RGB颜色通道(变为黑色),后偏移蓝色255
float[] matrix2 = new float[]{
-1, 0, 0, 0, 0,
0, -1, 0, 0, 0,
0, 0, -1, 0, 255,
0, 0, 0, 1, 0
};
ColorMatrix colorMatrix2 = new ColorMatrix(matrix2);
mRedPaint.setColorFilter(new ColorMatrixColorFilter(colorMatrix2));
canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
canvas.translate(350, 0);
//关闭RGB颜色通道(变为黑色),后偏移三色255
float[] matrix3 = new float[]{
-1, 0, 0, 0, 255,
0, -1, 0, 0, 255,
0, 0, -1, 0, 255,
0, 0, 0, 1, 0
};
ColorMatrix colorMatrix3 = new ColorMatrix(matrix3);
mRedPaint.setColorFilter(new ColorMatrixColorFilter(colorMatrix3));
canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
canvas.translate(350, 0);
float[] matrix4 = new float[]{
//只要把RGB三通道的色彩信息设置成一样:即:R=G=B,
// 为了保证图像亮度不变,同一个通道中的R+G+B=1
0.3086f, 0.6094f, 0.0820f, 0, 0,
0.3086f, 0.6094f, 0.0820f, 0, 0,
0.3086f, 0.6094f, 0.0820f, 0, 0,
0, 0, 0, 1, 0
};
ColorMatrix colorMatrix4 = new ColorMatrix(matrix4);
mRedPaint.setColorFilter(new ColorMatrixColorFilter(colorMatrix4));
canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
七、文字相关
字体.setTypeface(Typeface.SANS_SERIF);
对齐方式.setTextAlign(Paint.Align.LEFT);
字体大小.setTextSize(100);
1.对齐方式与内置字体:
对齐:
Paint.Align.
[#LEFT
|RIGHT
|CENTER
]
内置字体:Typeface.
[#DEFAULT
|DEFAULT_BOLD
|SANS_SERIF
|SERIF
|MONOSPACE
]
canvas.save();
canvas.translate(550, 1600);
mTextPaint.setTypeface(Typeface.SANS_SERIF);
mTextPaint.setTextAlign(Paint.Align.LEFT);
mTextPaint.setTextSize(100);
canvas.drawText("SANS_SERIF", 0, 0, mTextPaint);
Paint tempPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
tempPaint.setStrokeWidth(4);
tempPaint.setColor(Color.RED);
tempPaint.setStyle(Paint.Style.STROKE);
canvas.drawRect(0, - 100, mWinSize.x, 0, tempPaint);
canvas.translate(0, 150);
mTextPaint.setTextAlign(Paint.Align.RIGHT);
mTextPaint.setTypeface(Typeface.SERIF);
canvas.drawText("SERIF", 0, 0, mTextPaint);
canvas.drawRect(0, - 100, mWinSize.x, 0, tempPaint);
canvas.translate(0, 150);
mTextPaint.setTypeface(Typeface.MONOSPACE);
mTextPaint.setTextAlign(Paint.Align.CENTER);
canvas.drawText("MONOSPACE", 0, 0, mTextPaint);
canvas.drawRect(0, - 100, mWinSize.x, 0, tempPaint);
canvas.restore();
文字相关.png
2.创建字体:外部字体放在assets目录下
/**
* 创建字体
* @param canvas
*/
private void createTypeface(Canvas canvas) {
mTextPaint.setTextSize(50);
canvas.save();
canvas.translate(50, 1600);
mTextPaint.setTypeface(Typeface.MONOSPACE);
canvas.drawText("MONOSPACE", 0, 0, mTextPaint);
//粗体
canvas.translate(0, 100);
Typeface typeface = Typeface.create(Typeface.MONOSPACE, Typeface.BOLD);
mTextPaint.setTypeface(typeface);
canvas.drawText("MONOSPACE+BOLD", 0, 0, mTextPaint);
//斜体
canvas.translate(0, 100);
Typeface typeface2 = Typeface.create(Typeface.MONOSPACE, Typeface.ITALIC);
mTextPaint.setTypeface(typeface2);
canvas.drawText("MONOSPACE+ITALIC", 0, 0, mTextPaint);
//粗斜体
canvas.translate(0, 100);
Typeface typeface3 = Typeface.create(Typeface.MONOSPACE, Typeface.BOLD_ITALIC);
mTextPaint.setTypeface(typeface3);
canvas.drawText("MONOSPACE+BOLD_ITALIC", 0, 0, mTextPaint);
//使用外部字体
canvas.translate(0, 100);
Typeface myFont = Typeface.createFromAsset(getContext().getAssets(), "ACHAFSEX.TTF");
mTextPaint.setTypeface(myFont);
canvas.drawText("Hello I am Toly", 0, 0, mTextPaint);
canvas.restore();
}
创建字体.png
3.文字的测量:FontMetrics
1).字体测量类:FontMetrics
public static class FontMetrics {
public float top;//最顶
public float ascent;//
public float leading;
public float descent;
public float bottom;//最底
}
2).SERIF字体测试:(试了一下不同字体这几个属性都不同的,有的字体相差很大)
字体5线.png /**
* 获取字体尺寸信息
* @param canvas
*/
private void fontMetricsTest(Canvas canvas) {
canvas.save();
canvas.translate(100, 500);
mTextPaint.setTextSize(200);
mTextPaint.setTypeface(Typeface.SERIF);
canvas.drawText("I am Toly", 0, 0, mTextPaint);
//获取字体尺寸
Paint.FontMetrics fm = mTextPaint.getFontMetrics();
Log.e(TAG, "top: " + fm.top);
Log.e(TAG, "ascent: " + fm.ascent);
Log.e(TAG, "leading: " + fm.leading);
Log.e(TAG, "descent: " + fm.descent);
Log.e(TAG, "bottom: " + fm.bottom);
Paint tempPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
tempPaint.setStrokeWidth(1);
tempPaint.setColor(Color.RED);
tempPaint.setStyle(Paint.Style.STROKE);
canvas.drawLine(0, fm.top, mWinSize.x, fm.top, tempPaint);
tempPaint.setColor(Color.MAGENTA);
canvas.drawLine(0, fm.ascent, mWinSize.x, fm.ascent, tempPaint);
tempPaint.setColor(Color.parseColor("#4C17F9"));
canvas.drawLine(0, fm.leading, mWinSize.x, fm.leading, tempPaint);
tempPaint.setColor(Color.GREEN);
canvas.drawLine(0, fm.descent, mWinSize.x, fm.descent, tempPaint);
tempPaint.setColor(Color.parseColor("#E74EDD"));
canvas.drawLine(0, fm.bottom, mWinSize.x, fm.bottom, tempPaint);
canvas.restore();
}
2018-11-05 21:17:35.264 28726-28726/? E/PaintView: top: -209.57031
2018-11-05 21:17:35.264 28726-28726/? E/PaintView: ascent: -185.54688
2018-11-05 21:17:35.264 28726-28726/? E/PaintView: leading: 0.0
2018-11-05 21:17:35.264 28726-28726/? E/PaintView: descent: 48.828125
2018-11-05 21:17:35.264 28726-28726/? E/PaintView: bottom: 50.0
3).获取文字矩形区
String text = "I am Toly";
Rect textRect = new Rect();
mTextPaint.getTextBounds(text, 0, text.length(), textRect);
Log.e(TAG, textRect.toShortString());// [7,-152][886,49]
//绘制矩形
tempPaint.setColor(Color.parseColor("#66F4F628"));
tempPaint.setStyle(Paint.Style.FILL);
canvas.drawRect(textRect, tempPaint);
文字最小矩形区.png
4).文字的变形操作
mTextPaint.setTextScaleX(.5f);//水平伸缩
mTextPaint.setStrikeThruText(true);//删除线
mTextPaint.setUnderlineText(true);//下划线
mTextPaint.setTextSkewX(-.5f);//倾斜
其他效果.png
就先这样吧,还有很多不常用的,以后有需求遇到了,在加吧
后记:捷文规范
1.本文成长记录及勘误表
项目源码 | 日期 | 备注 |
---|---|---|
V0.1--无 | 2018-11-7 | Android关于Paint你所知道的和不知道的一切 |
2.更多关于我
笔名 | 微信 | 爱好 | |
---|---|---|---|
张风捷特烈 | 1981462002 | zdl1994328 | 语言 |
我的github | 我的简书 | 我的CSDN | 个人网站 |
3.声明
1----本文由张风捷特烈原创,转载请注明
2----欢迎广大编程爱好者共同交流
3----个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正
4----看到这里,我在此感谢你的喜欢与支持
icon_wx_200.png
网友评论