Almost this effect:
Full code:
package com.example.jadynai.loadinglovely.flicker; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.LinearGradient; import android.graphics.Matrix; import android.graphics.Shader; import android.support.annotation.IntRange; import android.support.v7.widget.AppCompatTextView; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.animation.LinearInterpolator; /** * @version: * @FileDescription: * @Author: Feng Rentang * @Since:2018/5/2 * @ChangeList: */ public class TextFlickerView extends AppCompatTextView { private static final String TAG = "TextFlickerView"; // width of flash public static final int SHADOW_W = 50; private Matrix mShadowMatrix; private LinearGradient mLinearGradient; private ValueAnimator mValueAnimator; private int mRepeatCount = 50; public TextFlickerView(Context context) { super(context); } public TextFlickerView(Context context, AttributeSet attrs) { super(context, attrs); } public TextFlickerView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); tryInitEngine (w); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Log.d(TAG, "onDraw: " + System.currentTimeMillis()); if (mLinearGradient != null) { mLinearGradient.setLocalMatrix(mShadowMatrix); } } private void tryInitEngine(int w) { if (mShadowMatrix == null) { if (w > 0) { //Control the Matrix of the shadow, and realize the glitter sliding effect through the change of the Matrix mShadowMatrix = new Matrix (); //Because LinearGradient is used, the color of Paint itself will be meaningless, so the color value of the starting point of colors must be consistent with the original color value int currentTextColor = getCurrentTextColor(); //Gradient color layer. x0, y0 are the coordinates of the starting point, x1, y1 are the coordinates of the end point mLinearGradient = new LinearGradient(0, 0, SHADOW_W, 0, new int[] {currentTextColor, Color.GREEN, Color.BLUE}, null, Shader.TileMode.CLAMP); //Brush settings Shader getPaint (). setShader (mLinearGradient); // Using property animation as the engine, the value changes from -SHADOW to the width of the TextView itself. Interval time is less than 1500ms mValueAnimator = ValueAnimator.ofFloat(-SHADOW_W, w).setDuration(1500); mValueAnimator.setInterpolator(new LinearInterpolator()); mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float value = (float) animation.getAnimatedValue(); //Matrix moves to achieve flash sliding mShadowMatrix.setTranslate (value, 0); invalidate(); } }); mValueAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationRepeat(Animator animation) { super.onAnimationRepeat(animation); //Reset the Matrix every time the animation repeats mShadowMatrix.reset (); } @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd (animation); mShadowMatrix.reset (); } }); mValueAnimator.setRepeatCount(mRepeatCount); } } } public void setDuration(@IntRange(from = 1, to = 15) int second) { mRepeatCount = second - 1; if (mValueAnimator != null) { mValueAnimator.setRepeatCount(mRepeatCount); } } public void start() { if (mValueAnimator == null) { postDelayed(new Runnable() { @Override public void run() { tryInitEngine(getWidth()); if (mValueAnimator != null) { mValueAnimator.start(); } } }, 100); } } @Override public void onWindowFocusChanged(boolean hasWindowFocus) { super.onWindowFocusChanged(hasWindowFocus); } @Override protected void onVisibilityChanged(View changedView, int visibility) { super.onVisibilityChanged(changedView, visibility); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); release(); } private void release() { if (mValueAnimator != null) { mValueAnimator.removeAllListeners(); mValueAnimator.cancel(); mValueAnimator = null; } mShadowMatrix = null; mLinearGradient = null; } }This is the original project address