Texto de color personalizado de Android

Personaliza un TextView que puede cambiar parcialmente de color, similar al efecto de las letras:

el efecto final es como se muestra en la imagen de arriba, que puede cambiar de color de izquierda a derecha o de derecha a izquierda.
La idea de la implementación es dividir el texto en dos partes para dibujar,
inserte la descripción de la imagen aquí
como este helloworld, establecer una posición y cambiar el color del pincel del lado izquierdo de la línea vertical a rojo, y el color del pincel detrás es el color predeterminado para dibujar en dos partes. Porque canvas.drawText finalmente se usa para dibujar, pero el texto "HelloWorld" es un todo y debe recortarse. El método específico es usar canvas.clipRect para cortar la parte desde el principio del texto hasta la posición roja al dibujar el texto de la izquierda, y recortar la posición de la línea roja hasta el final del texto de la derecha.
El efecto de cambio de color dinámico se logra cambiando la posición de la línea roja y redibujando continuamente.
clave

 @Override
    protected void onDraw(Canvas canvas) {
    
    
        int position = (int) (getWidth() * progress);
        if (currentOrientation == LEFT_TO_RIGHT) {
    
    
            drawText(canvas, changedPaint, 0, position);//绘制改变颜色的部份
            drawText(canvas, defaultPaint, position, getWidth()); //绘制默认颜色的部份
        } else {
    
    
            drawText(canvas, changedPaint, getWidth() - position, getWidth());
            drawText(canvas, defaultPaint, 0, getWidth() - position);
        }
    }

Se reescribe el método onDraw, se obtiene la posición de la segmentación según el progreso, y luego se llama dos veces a drawText para dibujar el texto desde la posición 0~ y la posición hasta el final respectivamente.

 private void drawText(Canvas canvas, Paint paint, int left, int right) {
    
    
        canvas.save();
        clipRect.set(left, 0, right, getBottom());
        canvas.clipRect(clipRect); //裁剪一部份绘制不同颜色
        // 给boundsRect赋值
        paint.getTextBounds(getText().toString(), 0, getText().toString().length(), boundsRect);
        int dx = (getWidth() - boundsRect.width()) / 2;  //让文字居中
        Paint.FontMetricsInt fontMetricsInt = paint.getFontMetricsInt();
        //fontMetricsInt.bottom为基线到底部的距离为正值,fontMetricsInt.top为基线到顶部的距离,为负值
        int dy = (fontMetricsInt.bottom - fontMetricsInt.top) / 2 - fontMetricsInt.bottom;//文字y中心到基线的距离
        int baseLine = getHeight() / 2 + dy; //基线的位置
        //drawText的第三个参数传的是baseLine的位置
        canvas.drawText(getText().toString(), dx, baseLine, paint);
        canvas.restore();
    }

La clave del método drawText es recortar clipRect según la posición. Debido a que hemos operado en el lienzo, debemos guardar el estado del lienzo cuando ingresamos y usar restaurar para restaurarlo después de que se complete el dibujo; de lo contrario, el dibujo en la parte derecha no será válido (porque solo la parte izquierda queda después de recortar el lienzo).
Finalmente, se proporciona un método para cambiar la posición dividida:

  public void setProgress(float progress) {
    
    //改变进度
        this.progress = progress;
        invalidate();
    }

Cuando lo usa externamente, puede ingresar directamente el porcentaje y calcular la posición de división real de acuerdo con la proporción en onDraw

  int position = (int) (getWidth() * progress);

A continuación se muestra el código completo --------------------------------------------- - ------------------------------------------------- - ------------------------------->>>>>>

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 android.widget.TextView;

import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;
//自定义可改变颜色的textView,跟歌词效果类似
public class ChangeColorTextView extends AppCompatTextView {
    
    
    private Paint defaultPaint;
    private Paint changedPaint;
    private float progress = 0f;
    private int currentOrientation = LEFT_TO_RIGHT;
    public static final int LEFT_TO_RIGHT = 0;
    public static final int RIGHT_TO_LEFT = 1;

    //限制输入参数
    @IntDef(value = {
    
    LEFT_TO_RIGHT, RIGHT_TO_LEFT})
    public @interface Orientation{
    
    

    }
    public ChangeColorTextView(Context context) {
    
    
        this(context, null);

    }


    public ChangeColorTextView(Context context, @Nullable AttributeSet attrs) {
    
    
        this(context, attrs, 0);
    }

    public ChangeColorTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    
    
        super(context, attrs, defStyleAttr);
        initPaint(context, attrs);
    }

    //设置从左到右还是右到左
    public void setCurrentOrientation(@Orientation int currentOrientation) {
    
    
        this.currentOrientation = currentOrientation;
    }

    //初始化画笔
    private void initPaint(Context context, AttributeSet attrs) {
    
    
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ChangeColorTextView);
        //读取自定义属性
        int defaultColor = typedArray.getColor(R.styleable.ChangeColorTextView_defaultColor, getTextColors().getDefaultColor());
        int changeColor = typedArray.getColor(R.styleable.ChangeColorTextView_changeColor, getTextColors().getDefaultColor());
        typedArray.recycle();
        defaultPaint = getPaintByColor(defaultColor);
        changedPaint = getPaintByColor(changeColor);
    }

    private Paint getPaintByColor(int Color) {
    
    
        Paint paint = new Paint();
        paint.setAntiAlias(true); //抗锯齿
        paint.setDither(true);//防抖
        paint.setColor(Color);
        paint.setTextSize(getTextSize());
        return paint;
    }

    @Override
    protected void onDraw(Canvas canvas) {
    
    
        int position = (int) (getWidth() * progress);
        if (currentOrientation == LEFT_TO_RIGHT) {
    
    
            drawText(canvas, changedPaint, 0, position);//绘制改变颜色的部份
            drawText(canvas, defaultPaint, position, getWidth()); //绘制默认颜色的部份
        } else {
    
    
            drawText(canvas, changedPaint, getWidth() - position, getWidth());
            drawText(canvas, defaultPaint, 0, getWidth() - position);
        }
    }

    Rect clipRect = new Rect();
    Rect boundsRect = new Rect();

    private void drawText(Canvas canvas, Paint paint, int left, int right) {
    
    
        canvas.save();
        clipRect.set(left, 0, right, getBottom());
        canvas.clipRect(clipRect); //裁剪一部份绘制不同颜色
        // 给boundsRect赋值
        paint.getTextBounds(getText().toString(), 0, getText().toString().length(), boundsRect);
        int dx = (getWidth() - boundsRect.width()) / 2;  //让文字居中
        Paint.FontMetricsInt fontMetricsInt = paint.getFontMetricsInt();
        //fontMetricsInt.bottom为基线到底部的距离为正值,fontMetricsInt.top为基线到顶部的距离,为负值
        int dy = (fontMetricsInt.bottom - fontMetricsInt.top) / 2 - fontMetricsInt.bottom;//文字y中心到基线的距离
        int baseLine = getHeight() / 2 + dy; //基线的位置
        //drawText的第三个参数传的是baseLine的位置
        canvas.drawText(getText().toString(), dx, baseLine, paint);
        canvas.restore();
    }

    public void setProgress(float progress) {
    
    //改变进度
        this.progress = progress;
        invalidate();
    }
}

atributos personalizados attrs.xml

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

Uso sencillo:
actividad.xml

   .................
  <com.sample.changecolortext.ChangeColorTextView
        android:id="@+id/changeColorTextView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="This is L2R ChangeColorTextView"
        android:textSize="20sp"
        app:changeColor="#ff0000"
        app:defaultColor="#ccc" />
   <SeekBar
        android:id="@+id/seekBar"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginTop="150dp" />
   .................

Use SeekBar en Actividad para cambiar el progreso

         .....................
        changeColorTextView=findViewById(R.id.changeColorTextView2);
        //改变方向
        //changeColorTextView.setCurrentOrientation(ChangeColorTextView.RIGHT_TO_LEFT);
        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
    
    
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
    
    
                changeColorTextView.setProgress(progress/100f);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
    
    

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
    
    

            }
        });
        .....................

encima.

Supongo que te gusta

Origin blog.csdn.net/weixin_40652755/article/details/127345440
Recomendado
Clasificación