android自定义变色文字

自定义一个可部分变色的TextView,类似歌词效果:

最终效果如上图,可以从左往右变色也可以从右往左变色。
实现的思路是将文字分成两部分来绘制,
在这里插入图片描述
如这个helloworld,定好一个位置将竖线左边的画笔颜色改成红色,后面的画笔颜色为默认颜色分成两部分来绘制。因为最终使用的是canvas.drawText来绘制,但是文字“HelloWorld”是一个整体,必须进行裁剪。具体方法是使用canvas.clipRect,绘制左边文字时裁剪文字开始到红色位置的部份,右边文字裁剪红线位置到文字末端部份。
动态变色效果则是通过改变红线位置,不断重绘即可。
关键代码

 @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);
        }
    }

重写了onDraw方法,根据progress得到分割的位置position,然后调用了两次drawText,分别绘制0~position和position到末端的文字。

 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();
    }

drawText方法的关键是根据position进行了clipRect裁剪。因为我们对画布进行了操作所以一进来需要保存画布的状态,在绘制完成后使用restore进行恢复,否则右边部分的绘制将会失效(因为画布裁剪只剩下了左边部分)。
最后提供一个改变分割位置的方法:

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

外部使用的时候直接输入百分比就可以,在onDraw中根据比例计算实际分割位置

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

下面是完整代码---------------------------------------------------------------------------------------------------------------------------->>>>>>

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();
    }
}

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>

简单使用:
activity.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" />
   .................

Activity中使用SeekBar改变进度

         .....................
        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) {

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

完。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 你可以使用 Android Studio 的 Text Watcher,在 afterTextChanged 回调中使用 SpannableString 和 ForegroundColorSpan 来实现文本循环变色的效果。具体实现需要根据你的需求进行适当调整。 ### 回答2: 要让文本循环变色,可以使用Android Studio中的TextView和Handler来实现。 首先,在布局文件中添加一个TextView,并设置id为"tvText"。然后在Java代码中,获取该TextView控件,并创建一个Handler对象。 ```java TextView tvText = findViewById(R.id.tvText); Handler handler = new Handler(); ``` 接下来,在Handler中创建一个Runnable对象,用于循环改变TextView的文本颜色。在Runnable的run方法中,可以使用TextView的setTextColor方法改变文本颜色。为了实现循环变色的效果,可以使用一个循环变量来控制颜色的选择。 ```java int[] colors = {Color.RED, Color.GREEN, Color.BLUE}; // 定义要循环的颜色 int index = 0; // 循环变量 Runnable runnable = new Runnable() { @Override public void run() { tvText.setTextColor(colors[index]); index = (index + 1) % colors.length; // 每次循环变量加1,并取余得到下一个颜色的索引 handler.postDelayed(this, 1000); // 延迟1秒后再执行下一次循环 } }; ``` 最后,在Activity的onCreate方法中,调用Handler中的postDelayed方法,实现循环变色的效果。 ```java @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); handler.postDelayed(runnable, 1000); // 延迟1秒后执行第一次循环变色 } ``` 这样,就实现了在Android Studio中让文本循环变色的效果。可以根据自己的需求,自定义要循环的颜色和间隔时间。 ### 回答3: 在Android Studio中实现文本循环变色,可以使用SpannableString类来实现。SpannableString是Android中的一个类,可以对文本的不同部分进行样式设置,包括颜色、大小、字体等。 下面是一个使用SpannableString实现文本循环变色的例子: 1. 首先,在xml布局文件中添加一个TextView控件: ``` <TextView android:id="@+id/text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" /> ``` 2. 在Java代码中获取TextView控件,并给文本设置SpannableString: ```java TextView textView = findViewById(R.id.text_view); String text = textView.getText().toString(); SpannableString spannableString = new SpannableString(text); ``` 3. 设置循环变色的颜色数组和循环次数: ```java int[] colors = {Color.RED, Color.BLUE, Color.GREEN}; // 设置颜色数组 int loopCount = 3; // 循环次数 ``` 4. 根据文本的长度和循环次数,给文本的每一部分设置不同的颜色: ```java for (int i = 0; i < text.length(); i++) { int colorIndex = i % (colors.length * loopCount) / loopCount; // 根据循环次数计算颜色索引 spannableString.setSpan(new ForegroundColorSpan(colors[colorIndex]), i, i + 1, Spannable.SPAN_INCLUSIVE_INCLUSIVE); // 设置颜色 } ``` 5. 将设置好的SpannableString应用到TextView上: ```java textView.setText(spannableString); ``` 通过以上步骤,我们就可以在Android Studio中实现文本循环变色的效果了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值