android中其实挺多功能需要渐变文字,图形效果的。
比如滚动歌词、今日头条tab滑动时,文字有一个渐变的过程
之前面试还被问过这个裁剪的波形图咋做。
今天做了这个滚动歌词,思路应该都差不多。
将文字居中显示
画辅助线
canvas.drawLine()是画线的方法
参数:顾名思义
没啥好说的
文字居中
canvas.drawText()是画文字的方法
看似没啥好说的,但是y点为啥叫baseline呢???
这里有个大坑,文字绘制不是根据文字的左下角而来的,是根据这个baseline来绘制的。
baseline
上图红线就是baseline,文字的绘制是根据baseline而来的,它保证大部分文字都是对齐的,就像拼音格子里的横线。
因为android坐标系是向下的,所以baseline往下是 +(正值),往上是 – (负值)
top与bottom
所有文字、符号的上下边界。top是负值,bottom是正值。原因是根据baseline为坐标系
ascent与desecnt
大部分文字的上下边界(排除特殊文字、符号,部分藏文、拉丁文等)。ascent是- (负值),desecnt是+(正值),因为是根据baseline为坐标系的
所以要居中应该是 (desecnt与ascent的差值/2) 即 (desecnt+ascent)/2
解释:文字高度: (desecnt – ascent) 直接除是不对的,因为绘制的时候还是要根据baseline的
这些文字的信息,在Paint.FontMetrics这个类
/** 绘制中间的文字 */
Paint paintText;
private void drawText(final Canvas canvas){
canvas.save();
if (paintText == null){
paintText = new Paint();
paintText.setTextSize(100);
paintText.setColor(Color.BLACK);
paintText.setAntiAlias(true);
}
//想要绘制文字真正居中
//宽直接屏幕/2 + Paint.Align.CENTER就行 或者 text的宽度的一半
int xCenter = (int) (getWidth()/2 - paintText.measureText(text)/2);
paintText.setTextAlign(Paint.Align.LEFT);
//高得 减去 baseline的上下差值/2
Paint.FontMetrics fontMetrics = paintText.getFontMetrics();
int yCenter = (int) (getHeight()/2 - (fontMetrics.ascent + fontMetrics.descent)/2);
canvas.drawText(text,xCenter,yCenter,paintText);
canvas.restore();
}
复制代码
绘制裁剪渐变色的文字
canvas.save(),canvas.restore() 这两是成对出现的,不然restore()如果没有save的话会报错。
他两用来保存、恢复。
可以想象成PS的图层,一组就是一个图层。
canvas.clipRect(rect);裁剪,可以裁剪画布,可以想象成PS的裁剪
思路:
下面用黑色的文字绘制一层,上面一层图层绘制彩色的文字,然后裁剪上面的图层,只显示需要展示的百分比的图像。
/** 绘制裁剪红色的文字 */
Paint paintText1;
private void drawText1(final Canvas canvas){
canvas.save();
int withText = (int) paintText.measureText(text);
int xCenter = (int) (getWidth()/2 - withText/2);
if (paintText1 == null){
paintText1 = new Paint();
paintText1.setTextSize(100);
paintText1.setTextAlign(Paint.Align.LEFT);
//设置渐变色
int [] colors = {Color.RED,Color.GREEN, Color.BLUE};
float[] position = {0f, 0.7f, 1.0f};
LinearGradient linearGradient = new LinearGradient(xCenter,0,xCenter+withText,0,colors,position, Shader.TileMode.CLAMP);
//设置着色器
paintText1.setShader(linearGradient);
paintText1.setAntiAlias(true);
}
Paint.FontMetrics fontMetrics = paintText1.getFontMetrics();
int yCenter = (int) (getHeight()/2 - (fontMetrics.ascent + fontMetrics.descent)/2);
//裁剪需要显示的部分 percentage是百分比,activity里传入float 0.0 - 1.0
Rect rect = new Rect(xCenter,0, (int) (xCenter + percentage * withText),getHeight());
canvas.clipRect(rect);
canvas.drawText(text,xCenter,yCenter,paintText1);
canvas.restore();
}
复制代码
invalidate()重绘,draw()
每次传入不同百分比的时候,需要重绘
public void changeColor(float percentage){
this.percentage=percentage;
invalidate();
}
复制代码