天天看點

一個TextView顯示2中顔色(動态變色)

之前寫了一次靜态的顔色,這次加上動畫效果。

先上效果:

一個TextView顯示2中顔色(動态變色)

自定義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);
            }
        });
    }
}