之前写了一次静态的颜色,这次加上动画效果。
先上效果:
自定义view:GradientColorDynamicTextView
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import androidx.annotation.Nullable;
/**
* 动态的 改变颜色
*/
public class GradientColorDynamicTextView extends androidx.appcompat.widget.AppCompatTextView {
// 当前朝向
private Direction mDirection = Direction.LEFT_TO_RIGHT;
// 绘制的朝向枚举
public enum Direction {
LEFT_TO_RIGHT, RIGHT_TO_LEFT
}
//2根画笔
Paint mOriginalPaint;//原始颜色
Paint mChangePaint;//改变后的颜色
public GradientColorDynamicTextView(Context context) {
this(context,null);
}
public GradientColorDynamicTextView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public GradientColorDynamicTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mOriginalPaint = new Paint();
mOriginalPaint.setAntiAlias(true);
mOriginalPaint.setTextSize(getTextSize());
mChangePaint = new Paint();
mChangePaint.setAntiAlias(true);
mChangePaint.setTextSize(getTextSize());
}
//默认不绘制
float mCurrentProgress = 0f;
@Override
protected void onDraw(Canvas canvas) {
//默认是从左到右
//获取文字的宽带
String text = getText().toString();
Rect bound = new Rect();
mOriginalPaint.getTextBounds(text,0,text.length(),bound);
//文字的开始位置的x坐标
int originStartX = (getWidth()-bound.width())/2;
//左边的宽度,根据progress给左边变色
int leftWidth=0;
if(mDirection.equals(Direction.LEFT_TO_RIGHT)){
mOriginalPaint.setColor(Color.RED);
mChangePaint.setColor(Color.GRAY);
//获取左边的宽度
leftWidth = (int) (getWidth() * mCurrentProgress);
}else {
mOriginalPaint.setColor(Color.GRAY);
mChangePaint.setColor(Color.RED);
//获取左边的宽度
leftWidth = (int) (getWidth() * (1-mCurrentProgress));
}
//左边
canvas.save();
Rect rectLeft = new Rect(0,0,leftWidth,getHeight());
canvas.clipRect(rectLeft);
//计算绘制origin的y坐标(baseline) 可复用
Paint.FontMetrics fontMetrics = mOriginalPaint.getFontMetrics();
float baseline = (getHeight()-fontMetrics.top-fontMetrics.bottom) / 2;
//canvas.save后,draw的时候,只会在clip出的区域绘制
canvas.drawText(text, originStartX, baseline, mOriginalPaint);
canvas.restore();
//右边,clip的右边区域
canvas.save();
Rect rectRight = new Rect(leftWidth,0,getWidth(),getHeight());
canvas.clipRect(rectRight);
//canvas.save后,draw的时候,只会在clip出的区域绘制
canvas.drawText(text, originStartX, baseline, mChangePaint);
canvas.restore();
}
public void setCurrentProgress(float progress){
mCurrentProgress = progress;
invalidate();
}
/**
* 设置方向
* @param direction
*/
public void setDirection(Direction direction){
mDirection = direction;
}
}
布局文件 gradient_tv_color :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.test.viewtest.GradientColorDynamicTextView
android:layout_marginTop="20dp"
android:id="@+id/gcdt"
android:padding="04dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="陕西省西安市雁塔区" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="从左到右"
android:onClick="changeLeftToRight"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="从右到左"
android:onClick="changeRightToLeft"/>
</LinearLayout>
Activity的使用:GradientColorTextViewActivity
public class GradientColorTextViewActivity extends AppCompatActivity {
private GradientColorDynamicTextView gcdt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gradient_tv_color);
gcdt = findViewById(R.id.gcdt);
}
public void changeLeftToRight(View view) {
gcdt.setDirection(GradientColorDynamicTextView.Direction.LEFT_TO_RIGHT);
@SuppressLint("ObjectAnimatorBinding")
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(gcdt,"progress",0,1f);
objectAnimator.setDuration(2000).start();
objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float progress = (float) animation.getAnimatedValue();
gcdt.setCurrentProgress(progress);
}
});
}
public void changeRightToLeft(View view) {
gcdt.setDirection(GradientColorDynamicTextView.Direction.RIGHT_TO_LEFT);
@SuppressLint("ObjectAnimatorBinding")
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(gcdt,"progress",0,1f);
objectAnimator.setDuration(2000).start();
objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float progress = (float) animation.getAnimatedValue();
gcdt.setCurrentProgress(progress);
}
});
}
}