之前寫了一次靜态的顔色,這次加上動畫效果。
先上效果:
自定義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);
}
});
}
}