Sunxin'Blog

自定义View - 一个文字两种颜色

自定义View-字体变色(一个文字两种颜色)

思路:主要是画笔Paint的使用和Canvas的裁切,需要继承自TextView。


  1. 一个文字两种颜色
  2. 颜色不同的朝向
  3. 与ViewPager整合

一种文字两种颜色

  • 自定义文字颜色属性,两种颜色,一个是原始颜色,一个是变化的颜色
1
2
3
4
5
6
<resources>
<declare-styleable name="ColorTrackTextView">
<attr name="originColor" format="color"/>
<attr name="changeColor" format="color"/>
</declare-styleable>
</resources>
  • 自定义ColorTrackTextView继承自TextView,获取自定义属性中的属性。初始化两支Paint,绘制两种颜色。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//两支画笔,一支绘制原始颜色,另一支绘制变化的颜色
private Paint mOrignPaint;//原始
private Paint mChangePaint;//变化
/**
* 初始化画笔,并获取属性值
* @param context
* @param attrs
*/
private void initPaint(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ColorTrackTextView);
int originColor = typedArray.getColor(R.styleable.ColorTrackTextView_originColor,
getTextColors().getDefaultColor());
int changeColor = typedArray.getColor(R.styleable.ColorTrackTextView_changeColor,
getTextColors().getDefaultColor());

mOrignPaint = getPaintByColor(originColor);
mChangePaint = getPaintByColor(changeColor);
//回收
typedArray.recycle();
}


private Paint getPaintByColor(int color) {
Paint paint = new Paint();
paint.setColor(color);
paint.setAntiAlias(true);//抗锯齿
paint.setDither(true);//防抖动
paint.setTextSize(getTextSize());//设置字体大小,就是TextView的字体大小
return paint;
}

一个文字不同颜色的实现主要是通过canvas.clipRect()来实现,通过裁切不同的文字部分然后使用不同颜色的画笔进行实时绘制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private void drawText(Canvas canvas,Paint paint,int start,int end){
//裁剪Rect,绘制不变色的文字部分
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();//回收画布
}
  • 指定布局文件
1
2
3
4
5
6
7
8
<com.sx.colortext.ColorTrackTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:changeColor="@color/colorAccent"
app:originColor="@color/colorPrimary"
android:text="Hello World!"
android:textSize="20sp"
/>

效果一

颜色不同朝向的实现

不同朝向的实现其实就是指定起始点与重点的位置即可。

  • 首先定义一个枚举类,初始化方向
1
2
3
4
5
private Direction mDirection = Direction.LEFT_TO_RIGHT;

public enum Direction {
LEFT_TO_RIGHT, RIGHT_TO_LEFT
}
  • 在onDraw()方法中根据方向进行绘制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Override
protected void onDraw(Canvas canvas) {

//根据进度把中间值计算出来
int middle = (int) (mCurrentProgress * getWidth());

if (mDirection == Direction.LEFT_TO_RIGHT) {
drawText(canvas, mChangePaint, 0, middle);
//绘制变色的文字部分
drawText(canvas, mOrignPaint, middle, getWidth());
} else if (mDirection == Direction.RIGHT_TO_LEFT) {
drawText(canvas, mChangePaint, getWidth()-middle, getWidth());
//绘制变色的文字部分
drawText(canvas, mOrignPaint, 0, getWidth()-middle);
}
}
  • 在为ColorTrackTextView对外提供两个方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 设置方向
* @param direction
*/
public void setDirection(Direction direction){
this.mDirection = direction;
}

/**
* 设置进度
* @param progress
*/
public void setCurrentProgress(float progress){
this.mCurrentProgress = progress;
invalidate();//不断重绘
}
  • 调用,设置位移的属性动画
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void rightToLeft(View view) {
mTrackTextView.setDirection(ColorTrackTextView.Direction.RIGHT_TO_LEFT);
//属性动画
ObjectAnimator animator = ObjectAnimator.ofFloat(mTrackTextView, "translationX", 0, 1);
animator.setDuration(2000);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float fraction = animation.getAnimatedFraction();
mTrackTextView.setCurrentProgress(fraction);
}
});

animator.start();
}
  • 实现的效果

效果二

与ViewPager结合,实现类似TabLayout的效果

采用LinearLayout动态添加View的方式配合ViewPager+Fragment实现效果,最后实现的效果如下图

效果三

-------------本文结束感谢您的阅读-------------