自定义view - 玩转字体变色

自定义View步骤:
1>:values__attrs.xml,定义自定义属性;
2>:在第三个构造方法中获取自定义属性;
3>:onMeasure【不是必须的】;
4>:onDraw:绘制代码全都在onDraw中写的;
这篇文章主要是结合属性动画自定义一个文字变色的view。先来看效果图。
自定义view - 玩转字体变色_第1张图片技术分析:
不能用TextView,因为系统的TextView只能有一种颜色,需要ColorTraceTextView,继承TextView,而不是继承View,原因是:
1>:继承TextView不用自己手动实现onMeasure、onDraw,系统已经实现了;
2>:textColor、textSize属性TextView已经实现了,不用自己实现;
3>: 自定义属性a.不变的颜色 origincolor b.变化的颜色 changcolor

1.字体颜色

自定义属性:attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="ColorTrackText">
        <attr name="originColor" format="color"/>
        <attr name="changeColor" format="color"/>
    </declare-styleable>
</resources>

使用属性:avtivity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="16dp"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    android:paddingTop="16dp"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <com.example.view_day04.ColorTrackTextView
        android:id="@+id/ColorTrackTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="hello world"
        android:textSize="20sp"
        app:changeColor ="@color/purple_200"
        app:originColor = "@color/black"
        />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="左到右"
        android:onClick="leftToRight"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="右到左"
        android:onClick="rightToLeft"/>

</LinearLayout>

2.自定义View–初始化、获取画笔、绘制、实现不同朝向

ColorTrackTextView.java

2.1.初始化、画笔、 绘制

public class ColorTrackTextView extends TextView{

    // 绘制不变色的画笔
    private Paint mOriginPaint ;
    // 绘制变色的画笔
    private Paint mChangePaint ;
    private float mCurrentProgress = 0.0f;
    private Direction mDirection;
    //实现不同朝向
    public enum Direction {
        LEFT_TO_RIGHT,RIGHT_TO_LEFT
    }
    public ColorTrackTextView(Context context) {
        this(context, null);
    }

    public ColorTrackTextView(Context context, @Nullable @org.jetbrains.annotations.Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ColorTrackTextView(Context context, @Nullable @org.jetbrains.annotations.Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initPaint(context, attrs);
    }

    private void initPaint(Context context, AttributeSet attrs)
    {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ColorTrackText);
        // 此处颜色传递默认值,防止你在布局文件中没有指定颜色
        int originColor = typedArray.getColor(R.styleable.ColorTrackText_originColor, getTextColors().getDefaultColor());
        int changeColor = typedArray.getColor(R.styleable.ColorTrackText_changeColor, getTextColors().getDefaultColor());
        mOriginPaint = getPaintByColor(originColor);
        mChangePaint = getPaintByColor(changeColor);
        typedArray.recycle();
    }

    private Paint getPaintByColor(int color) {
        Paint paint = new Paint() ;
        // 给画笔设置颜色
        paint.setColor(color);
        // 设置抗锯齿
        paint.setAntiAlias(true);
        // 仿抖动
        paint.setDither(true);
        // 设置文字大小,拿到布局中的Textsize
        paint.setTextSize(getTextSize());
        return paint;
    }

    //利用cliprect可以裁剪,左边用一个画笔去画,右边用另一个画笔去画 不断地改变中间值
    @Override
    protected void onDraw(Canvas canvas) {

        //根据进度把中间值是算出来
        int middle = (int)(mCurrentProgress * getWidth());
        if (mDirection == Direction.LEFT_TO_RIGHT) {
            //绘制不变色的
            drawText(canvas,mOriginPaint,0, middle);
            //绘制变色的
            drawText(canvas,mChangePaint,middle, getWidth());
        } else {
            // 右-左:
            drawText(canvas , mChangePaint , getWidth()-middle , getWidth());
            drawText(canvas , mOriginPaint , 0 , getWidth()-middle);
        }
    }

    /**
     * 画文字
     */
    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;

        // 基线计算方式
        Paint.FontMetricsInt fontMetricsInt = paint.getFontMetricsInt();
        int dy = (fontMetricsInt.bottom-fontMetricsInt.top)/2-fontMetricsInt.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();
    }

    /**
     * 设置改变的颜色
     */
    public void setChangeColor(int color){
        this.mChangePaint.setColor(color);
    }

}

你可能感兴趣的:(android)