文字的测量高度
宽度 测量调用 measureText
文字居中显示
高度的计算 :
top + bottom -> bottom - top 最大高度
ascent+descent --》 decent - accent 正常高度
(ascent+descent ) 因为ascent为负数 所以 ---》descent-ascent
Height/2 + (decent - accent)/2 - decent
= Height/2 + decent/2 -accent/2 -decent
= Height/2 - (decent + accent)/2
所以高度居中的基准
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
float baseline = getHeight()/2 - (fontMetrics.descent + fontMetrics.ascent)/2;
文字居中
float left = getWidth()/2 -width/2;
float right = left + width*mPercent;
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
float baseline = getHeight()/2 - (fontMetrics.descent + fontMetrics.ascent)/2;
canvas.drawText(mText,left,baseline ,paint);
1.自定义属性
attrs.xml文件中
<declare-styleable name="ColorTrackTextView">
<attr name="originColor" format="color"/>
<attr name="changeColor" format="color"/>
</declare-styleable>
自定义类ColorTrackTextView
public class ColorTrackTextView extends TextView {
// 1. 实现一个文字两种颜色 - 绘制不变色字体的画笔
private Paint mOriginPaint;
// 实现一个文字两种颜色 - 绘制变色字体的画笔
private Paint mChangePaint;
public ColorTrackTextView(Context context) {
this(context,null);
}
public ColorTrackTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ColorTrackTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initPaint(context, attrs);
}
/**
* 初始化画笔
*/
private void initPaint(Context context, AttributeSet attrs) {
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ColorTrackTextView);
int originColor = array.getColor(R.styleable.ColorTrackTextView_originColor, getTextColors().getDefaultColor());
int changeColor = array.getColor(R.styleable.ColorTrackTextView_changeColor, getTextColors().getDefaultColor());
mOriginPaint = getPaintByColor(originColor);
mChangePaint = getPaintByColor(changeColor);
// 回收
array.recycle();
}
/**
* 根据颜色获取画笔
*/
private Paint getPaintByColor(int color) {
Paint paint = new Paint();
// 设置颜色
paint.setColor(color);
// 设置抗锯齿
paint.setAntiAlias(true);
// 防抖动
paint.setDither(true);
// 设置字体的大小 就是TextView的字体大小
paint.setTextSize(getTextSize());
return paint;
}
2.绘制Text
//clipRect 可以裁剪 左边用一个画笔去画 右边用另一个画笔去画 不断地改变中间值
@Override
protected void onDraw(Canvas canvas) {
// super.onDraw(canvas);
//裁剪区域
//根据进度把中间值计算出来
// 根据进度把中间值算出来
int middle = (int) (mCurrentProgress * getWidth());
// 从左变到右
if(mDirection == Direction.LEFT_TO_RIGHT) { // 左边是红色右边是黑色
// 绘制变色
drawText(canvas, mChangePaint , 0, middle);
drawText(canvas, mOriginPaint, middle, getWidth());
}else{
// 右边是红色左边是黑色
drawText(canvas, mChangePaint, getWidth()-middle, getWidth());
// 绘制变色
drawText(canvas, mOriginPaint, 0, getWidth()-middle);
}
}
/**
* 绘制Text
* @param canvas
* @param paint
* @param start
* @param end
*/
private void drawText(Canvas canvas,Paint paint,int start,int end){
canvas.save();
// 绘制不变色
Rect rect = new Rect(start, 0, end, getHeight());
canvas.clipRect(rect);
// 我们自己来画
String text = getText().toString();
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
// 获取字体的宽度
int x = getWidth() / 2 - bounds.width() / 2;
// 基线baseLine
Paint.FontMetricsInt fontMetrics = paint.getFontMetricsInt();
int dy = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
int baseLine = getHeight() / 2 + dy;
canvas.drawText(text, x, baseLine, paint);// 这么画其实还是只有一种颜色
canvas.restore();
}
3.设置不同方向
private Direction mDirection=Direction.LEFT_TO_RIGHT;
public enum Direction{
LEFT_TO_RIGHT,RIGHT_TO_LEFT
}
4.提供对外开放的方法
public void setmDirection(Direction direction) {
this.mDirection = direction;
}
public void setmCurrentProgress(float currentProgress) {
this.mCurrentProgress = currentProgress;
invalidate();
}
public void setChangeColor(int changeColor) {
this.mChangePaint.setColor(changeColor);
}
public void setOriginColor(int originColor) {
this.mOriginPaint.setColor(originColor);
}
5.具体使用
tv = (ColorTrackTextView) findViewById(R.id.tv);
ValueAnimator valueAnimator = ObjectAnimator.ofFloat(0, 1);
valueAnimator.setDuration(2000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float animatedValue = (float) animation.getAnimatedValue();
tv.setmCurrentProgress(animatedValue);
}
});
valueAnimator.start();