先上效果图

https://img-blog.csdnimg.cn/95edc6546012472eb2411d07a334817b.jpeg
https://img-blog.csdnimg.cn/0dd4d09175f94148af4748334e1a490a.jpeg
先上自定义view
public class FontColorView extends androidx.appcompat.widget.AppCompatTextView {
private int sameColor= Color.BLACK;
private int changeColor=Color.GREEN;
private Paint mSamePaint ;
private Paint mChangePaint ;
public FontColorView(Context context) {
this(context,null);
}
public FontColorView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public FontColorView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.FontColorView);
sameColor = array.getColor(R.styleable.FontColorView_sameColor,sameColor);
changeColor = array.getColor(R.styleable.FontColorView_changeColor,changeColor);
array.recycle();
initSamePaint();
initChangePaint();
}
private void initSamePaint(){
mSamePaint = new Paint();
mSamePaint.setColor(sameColor);
mSamePaint.setAntiAlias(true);
mSamePaint.setTextSize(getTextSize()); // 获取到文字大小
}
private void initChangePaint(){
mChangePaint = new Paint();
mChangePaint.setColor(changeColor);
mChangePaint.setAntiAlias(true);
mChangePaint.setTextSize(getTextSize()); // 获取到文字大小
}
private float mCurrentPro = 0.5F;
public void setmCurrentPro(float mCurrentPro) {
this.mCurrentPro = mCurrentPro;
invalidate();
}
public enum DirectionEnum{
TOLEFT,
TORIGHT
}
private DirectionEnum directionEnum ;
public void setDirectionEnum(DirectionEnum directionEnum) {
this.directionEnum = directionEnum;
}
@Override
protected void onDraw(Canvas canvas) {
canvas.save(); // 保存下 画布 后面执行裁剪操作
int middle = (int) (mCurrentPro*getWidth()); // 计算中间值
if(directionEnum ==DirectionEnum.TORIGHT){
drawText(0,middle,canvas,mChangePaint);
drawText(middle,getWidth(),canvas,mSamePaint);
}else {
drawText(getWidth()-middle,getWidth(),canvas,mChangePaint);
drawText(0,getWidth()-middle,canvas,mSamePaint);
}
}
private void drawText(int start ,int end ,Canvas canvas,Paint mPaint){
canvas.save();
Rect mClipRect = new Rect(start,0,end,getHeight()) ;
canvas.clipRect(mClipRect); // 裁剪区域
String str = getText().toString() ;// 获取到文本
Rect boundsRect = new Rect() ;
mPaint.getTextBounds(str,0,str.length(),boundsRect);
int x = getWidth()/2-boundsRect.width()/2;
Paint.FontMetricsInt fontMetricsInt = mPaint.getFontMetricsInt();//获取到文本的基线
int baseLine = ( fontMetricsInt.bottom-fontMetricsInt.top)/2-fontMetricsInt.descent;
int y = getHeight()/2+baseLine ;
canvas.drawText(str,x,y,mPaint);
canvas.restore();
}
}
接下来是自定义属性文件
<declare-styleable name="FontColorView">
<attr name="sameColor" format="color"/>
<attr name="changeColor" format="color"/>
</declare-styleable>
效果测试方法
public void changeColor(View view) {
if(isShow){
isShow = false;
font_view_tv.setDirectionEnum(FontColorView.DirectionEnum.TORIGHT);
ValueAnimator valueAnimator = ObjectAnimator.ofFloat(0,1);
valueAnimator.setDuration(1000);
valueAnimator.addUpdateListener(animation -> {
float sds = (float) animation.getAnimatedValue();
font_view_tv.setmCurrentPro(sds);
});
valueAnimator.start();
}else {
isShow = true ;
font_view_tv.setDirectionEnum(FontColorView.DirectionEnum.TOLEFT);
ValueAnimator valueAnimator = ObjectAnimator.ofFloat(0,1);
valueAnimator.setDuration(1000);
valueAnimator.addUpdateListener(animation -> {
float sds = (float) animation.getAnimatedValue();
font_view_tv.setmCurrentPro(sds);
});
valueAnimator.start();
}
}