1. 自定义属性声明 和 使用
<declare-styleable name="ColorTrackTextView">
<attr name="originColor" format="color" />
<attr name="changeColor" format="color" />
</declare-styleable>
<com.tom.architect02.ui10.day04.ColorTrackTextView
android:id="@+id/color_track_tv"
android:textSize="20sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:changeColor="#ff8000"
android:text="Hello World!" />
2. 使用自定义的ColorTrackTextView
public class MainActivityUI04 extends AppCompatActivity {
private ColorTrackTextView mColorTrackTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_ui04);
mColorTrackTextView = (ColorTrackTextView) findViewById(R.id.color_track_tv);
}
public void leftToRight(View view){
mColorTrackTextView.setDirection(ColorTrackTextView.Direction.LEFT_TO_RIGHT);
ValueAnimator valueAnimator = ObjectAnimator.ofFloat(0, 1);
valueAnimator.setDuration(2000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float currentProgress = (float) animation.getAnimatedValue();
mColorTrackTextView.setCurrentProgress(currentProgress);
}
});
valueAnimator.start();
}
public void rightToLeft(View view){
mColorTrackTextView.setDirection(ColorTrackTextView.Direction.RIGHT_TO_LEFT);
ValueAnimator valueAnimator = ObjectAnimator.ofFloat(0, 1);
valueAnimator.setDuration(2000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float currentProgress = (float) animation.getAnimatedValue();
mColorTrackTextView.setCurrentProgress(currentProgress);
Log.e("TAG","currentProgress -> "+currentProgress);
}
});
valueAnimator.start();
}
}
3. ColorTrackTextView实现
package com.tom.architect02.ui10.day04;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import com.tom.architect02.R;
/**
* Added by Tom on 2024/06/05.
* 字体变色效果
*/
public class ColorTrackTextView extends androidx.appcompat.widget.AppCompatTextView {
// 1. 实现一个文字两种颜色 - 绘制不变色字体的画笔
private Paint mOriginPaint;
// 1. 实现一个文字两种颜色 - 绘制变色字体的画笔
private Paint mChangePaint;
// 1. 实现一个文字两种颜色 - 当前的进度
private float mCurrentProgress = 0.0f;
// 2.实现不同朝向
private Direction mDirection = Direction.LEFT_TO_RIGHT;
public enum Direction {
LEFT_TO_RIGHT, RIGHT_TO_LEFT
}
public ColorTrackTextView(Context context) {
this(context, null);
}
public ColorTrackTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ColorTrackTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initPaint(context, attrs);
}
private void initPaint(Context context, AttributeSet attrs) {
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ColorTrackTextView);
int originColor = array.getColor(R.styleable.ColorTrackTextView_originColor, getTextColors().getDefaultColor());
int changeColor = array.getColor(R.styleable.ColorTrackTextView_changeColor, getTextColors().getDefaultColor());
mOriginPaint = getPaintByColor(originColor);
mChangePaint = getPaintByColor(changeColor);
// 回收
array.recycle();
}
/**
* 1.根据颜色获取画笔
*/
private Paint getPaintByColor(int color) {
Paint paint = new Paint();
paint.setColor(color); // 设置颜色
paint.setAntiAlias(true); // 设置抗锯齿
paint.setDither(true); // 防抖动
// 设置字体的大小 就是TextView的字体大小
paint.setTextSize(getTextSize());
return paint;
}
// 1. 一个文字两种颜色
// 利用clipRect的API 可以裁剪 左边用一个画笔去画 右边用另一个画笔去画 不断的改变中间值
@Override
protected void onDraw(Canvas canvas) {
// super.onDraw(canvas); // 不适用系统的onDraw方法。
// canvas.clipRect(); 裁剪区域
// 根据进度把中间值算出来,不断地计算中间值 middle
int middle = (int) (mCurrentProgress * getWidth());
// 从左变到右
if (mDirection == Direction.LEFT_TO_RIGHT) { // 左边是红色右边是黑色
// 绘制变色. 左边用一个画笔,右边用一个画笔。
drawText(canvas, mChangePaint, 0, middle); // 左边是红色
drawText(canvas, mOriginPaint, middle, getWidth()); // 右边是原来的黑色
} else {
// 右边是红色,左边是黑色
drawText(canvas, mChangePaint, getWidth() - middle, getWidth());
// 左边的 绘制原始默认色
drawText(canvas, mOriginPaint, 0, getWidth() - middle);
}
}
/**
* 绘制Text,先裁剪好画布,再绘制。或先绘制,再裁剪。
* @param canvas 画布
* @param paint 画笔
* @param start 开始位置
* @param end 结束位置
*/
private void drawText(Canvas canvas, Paint paint, int start, int end) {
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(); // 释放画布,释放了才能再次裁剪。
}
public void setDirection(Direction direction) {
this.mDirection = direction;
}
public void setCurrentProgress(float currentProgress) {
this.mCurrentProgress = currentProgress;
invalidate(); // 刷新UI
}
public void setChangeColor(int changeColor) {
this.mChangePaint.setColor(changeColor);
}
public void setOriginColor(int originColor) {
this.mOriginPaint.setColor(originColor);
}
}
// 内涵段子 app,28节课。
网友评论