先上效果图
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(); } }