应广大网友要求,上图吧
流光动画是先写一个TextView,然后上面再覆盖一层FlowingLightView
流光字体是直接用ShineTextView,具体效果就看图吧
Android流光动画,直接上代码
/**
* 流光动画
*/
public class FlowingLightView extends View {
private Paint mPaint;
private Path mPath;
private LinearGradient mLinearGradient;
private ValueAnimator mValueAnimator;
public FlowingLightView(Context context) {
this(context, null);
}
public FlowingLightView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public FlowingLightView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mPaint = new Paint();
mPath = new Path();
}
private void initPointAndAnimator(int w, int h) {
Point point1 = new Point(0, 0);
Point point2 = new Point(w, 0);
Point point3 = new Point(w, h);
Point point4 = new Point(0, h);
mPath.moveTo(point1.x, point1.y);
mPath.lineTo(point2.x, point2.y);
mPath.lineTo(point3.x, point3.y);
mPath.lineTo(point4.x, point4.y);
mPath.close();
// 斜率k
float k = 0f * h / w;
// 偏移
float offset = 1f * w / 8;
// 0f - offset * 2 为数值左边界(屏幕外左侧), w + offset * 2为数值右边界(屏幕外右侧)
// 目的是使光影走完一遍,加一些时间缓冲,不至于每次光影移动的间隔都那么急促
mValueAnimator = ValueAnimator.ofFloat(0f - offset/2, w + offset/2);
mValueAnimator.setRepeatCount(-1);
mValueAnimator.setInterpolator(new LinearInterpolator());
mValueAnimator.setDuration(8000);
mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float) animation.getAnimatedValue();
mLinearGradient = new LinearGradient(value, k * value, value + 2, k * (value + 2),
new int[]{Color.parseColor("#00FFE5EE"), Color.parseColor("#FFE5EE"), Color.parseColor("#00FFE5EE")}, null, Shader.TileMode.CLAMP);
mPaint.setShader(mLinearGradient);
invalidate();
}
});
mValueAnimator.start();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
initPointAndAnimator(widthSize, heightSize);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(mPath, mPaint);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mValueAnimator.cancel();
}
}
android 流光字体
public class ShineTextView extends AppCompatTextView {
private LinearGradient mLinearGradient;
private Matrix mGradientMatrix;
private Paint mPaint;
private int mViewWidth = 0;
private int mTranslate = 0;
public ShineTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (mViewWidth == 0) {
mViewWidth = getMeasuredWidth();
if (mViewWidth > 0) {
mPaint = getPaint();
mLinearGradient = new LinearGradient(
0,
0,
mViewWidth/8,
0,
new int[]{0xFFFF5997, 0xFFFFE5EE, 0xFFFF5997},
null,
Shader.TileMode.CLAMP);
mPaint.setShader(mLinearGradient);
mGradientMatrix = new Matrix();
}
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mGradientMatrix != null) {
mTranslate += mViewWidth / 10;
if (mTranslate > 1.5 * mViewWidth) {
mTranslate = -mViewWidth / 2;
}
mGradientMatrix.setTranslate(mTranslate, 0);
mLinearGradient.setLocalMatrix(mGradientMatrix);
postInvalidateDelayed(100);
}
}
}