在特定时间段内为 TextView 着色 Android

Coloring TextView during a certain time period Android

有没有办法在特定时间段内为 TextView 中的文本或 Android 中的其他内容着色。所以它会以全白文本开始,然后 coloring 会从左向右移动并在某个 duration 期间填满它。
因此,例如,如果 duration 将是 10,则整条线应在 10 秒内变为彩色,但它也应以相同的速度移动。

看起来像这样:

有一种方法可以在 IOS 上用 CATextLayer 做到这一点,但我还没有找到在 Android 上做到这一点的方法。

有一种方法可以做到这一点优化,简单,流畅,美观:Vector Animated Drawables (API21+)

有很多教程(例如 this 视频)展示了如何制作精美的动画。基本上步骤如下:

  • 为您的文本创建两张 SVG 矢量图像,一张为正常颜色,另一张为 彩色字母。例如,您可以在 Adob​​e Illustrator 中轻松完成此操作。
  • 将两者导入 shapeshifter.design

  • 根据自己的喜好为第二层(彩色图层)制作动画。

  • 将生成的 xml 文件复制到您的可绘制对象中,您就完成了!

祝你好运!

您可以使用 spannable 文本和 Foreground Color Span 并一次为一个字符设置动画

我去年刚创建了一个自定义的TextView,这是我的class

public class AKChangeColorTextView extends TextView {
    public AKChangeColorTextView(Context context) {
        this(context,null);
    }
    String TAG = "AKChangeColorTextView";
    public AKChangeColorTextView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    RectF mRectF;
    float mX;
    float mY;
    public AKChangeColorTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setColor(Color.BLUE);
        PorterDuffXfermode mode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
        mPaint.setXfermode(mode);
        float x = 60;
        float y = 10;
        mY =    0;
        mRectF = new RectF(x, y, x + 50, y + 50);
        mTPaint = getPaint();
        mX = 0;
    }

    Paint mPaint;
    TextPaint mTPaint;
    Bitmap shadowBitmap ;
    Rect bounds = new Rect();
    Canvas textCanvas;

    @Override
    protected void onDraw(Canvas canvas) {
//        super.onDraw(canvas);
        if (shadowBitmap == null) {
            shadowBitmap = Bitmap.createBitmap(getMeasuredWidth(),getMeasuredHeight(), Bitmap.Config.ARGB_8888);
        }
        if (textCanvas == null) {
            textCanvas = new Canvas(shadowBitmap);
        }
        textCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
        if (mTPaint == null) {
            mTPaint = getPaint();
        }
        String content  = getText().toString();
        mTPaint.getTextBounds(content,0,content.length(),bounds);
        textCanvas.drawText(content,0,bounds.height(),mTPaint);
        mRectF.set(colorLeft,mY,colorRight,mY+bounds.height()+10);
        textCanvas.drawRect(mRectF,mPaint);
        canvas.drawBitmap(shadowBitmap,0,0,null);
    }
    float colorLeft;
    float colorRight;
    public void setXOffset(float left,float right){
        colorLeft = left;
        colorRight = right;
        invalidate();
    }

}

我的演示代码:

class MainActivity : AppCompatActivity() {
    val TAG = "MainActivity"
    lateinit var countDownTimer:CountDownTimer
    var currentOffsetx = 0
    var textWidth = 0
    var isIncrease = true
    lateinit var txt:AKChangeColorTextView
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        setSupportActionBar(toolbar)
        (findViewById<View>(R.id.tv_hello) as AKChangeColorTextView).apply{
            txt = this
        }

        countDownTimer = object:CountDownTimer(300000,200){
            override fun onFinish() {
            }

            override fun onTick(millisUntilFinished: Long) {
                if (textWidth == 0) {
                    textWidth = txt.width
                }
                if (currentOffsetx <= textWidth) {
                    if (isIncrease) {
                        currentOffsetx += 10
                        currentOffsetx = min(currentOffsetx, textWidth)
                    } else {
                        currentOffsetx -= 10
                        currentOffsetx = max(currentOffsetx, 0)
                    }
                }
                if (currentOffsetx == textWidth) {
                    isIncrease = false
                }else if (currentOffsetx == 0) {
                    isIncrease = true
                }
                txt.setXOffset(0f,currentOffsetx.toFloat())
                Log.w(TAG,"check current tick:$millisUntilFinished,offsetx:$currentOffsetx,txtWidth:$textWidth")
            }
        }
        countDownTimer.start()
    }

}

我的xml布局:

<com.example.administrator.myapplication.AKChangeColorTextView
            android:id="@+id/tv_hello"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="I Found a Love For Aolphn"
            android:textColor="#000000"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"/>

效果如下