UI 04: 字体变色TextView,一个TextView两种

2024-06-05  本文已影响0人  xqiiitan

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节课。
上一篇 下一篇

猜你喜欢

热点阅读