package com.example.lightline;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver;
import androidx.annotation.Nullable;
public class LightingView extends View {
private Shader mGradient;
private Matrix mGradientMatrix;
private Paint mPaint;
private int mViewWidth = 0, mViewHeight = 0;
private float mTranslateX = 0, mTranslateY = 0;
private boolean mAnimating = false;
private RectF rect;
private ValueAnimator valueAnimator;
private boolean autoRun = true; //是否自動運行動畫
public String TAG = "LightingView ";
private long timeMillis;
public LightingView(Context context) {
super(context);
init();
}
public LightingView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public LightingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
timeMillis = System.currentTimeMillis();
rect = new RectF();
mPaint = new Paint();
initGradientAnimator();
}
public void setAutoRun(boolean autoRun) {
this.autoRun = autoRun;
}
// onSizeChanged 這個方法肯定在onMeasure 之後,因爲這個方法可以獲取到真正的寬高,
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// onMeasure 方法之後寬高就會測量完畢
Log.i(TAG, "onSizeChanged ------------ ==" + mViewWidth);
if (mViewWidth == 0) {
mViewWidth = getWidth();
mViewHeight = getHeight();
if (mViewWidth > 0) {
//亮光閃過
// Shader 著色器的意思
// Shader.TileMode.CLAMP 表示繪製邊緣
// Shader.TileMode.MIRROR 表示鏡像繪製
// Shader.TileMode.REPEAT 表示重複繪製
// 繪製寬度爲 控件寬度一般,高度爲控件高度的過渡view
mGradient = new LinearGradient(0, 0, getMeasuredWidth() / 2, getMeasuredHeight(),
new int[]{0x007965FF, 0xff7965FF, 0xffD6D8FF},
new float[]{0.0f, 0.4f, 1f},
Shader.TileMode.REPEAT);// 以邊緣色調繪製剩餘的部分
// 給paint 添加着色器
mPaint.setShader(mGradient);
// setLayerType(View.LAYER_TYPE_SOFTWARE, null);//關掉硬件加速
//
// PorterDuff.Mode.DST 丟棄原像素,使目標保持不變,這裏的目標指的是,LightView 的背景圖片
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DARKEN));
mGradientMatrix = new Matrix();
// 這個是控制繪製時最開始的 偏移量,
// mGradientMatrix.setTranslate(-1 *mViewWidth , mViewHeight);
mGradient.setLocalMatrix(mGradientMatrix);
rect.set(0, 0, w, h);
}
}
}
//
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.i(TAG, "onDraw ------------");
if (mAnimating && mGradientMatrix != null) {
// 表示繪製,一個矩形,
canvas.drawRoundRect(rect, 15, 15, mPaint);
}
}
private void initGradientAnimator() {
valueAnimator = ValueAnimator.ofFloat(0, 1);
valueAnimator.setDuration(1000);
valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float v = (Float) animation.getAnimatedValue();
// Log.i(TAG,System.currentTimeMillis()- timeMillis +" timeMi");
//❶ 改變每次動畫的平移x、y值,範圍是[-mViewWidth, mViewWidth]
mTranslateX = 2 * mViewWidth * v - mViewWidth * 1;
mTranslateY = mViewHeight * v;
//❷ 平移matrix, 設置平移量
if (mGradientMatrix != null) {
mGradientMatrix.setTranslate(mTranslateX, mTranslateY);
}
//❸ 設置線性變化的matrix
if (mGradient != null) {
mGradient.setLocalMatrix(mGradientMatrix);
}
//❹ 重繪
invalidate();
// if (v >= 1) {
// System.out.println("stop ----------------------");
// stopAnimation();
// }
}
});
if (autoRun) {
getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
getViewTreeObserver().removeGlobalOnLayoutListener(this);
mAnimating = true;
if (valueAnimator != null) {
Log.i(TAG, System.currentTimeMillis() - timeMillis + " timeMi");
// valueAnimator.start();
}
}
});
}
}
//停止動畫
public void stopAnimation() {
if (mAnimating && valueAnimator != null) {
mAnimating = false;
valueAnimator.cancel();
invalidate();
}
}
//開始動畫
public void startAnimation() {
if (!mAnimating && valueAnimator != null) {
mAnimating = true;
valueAnimator.start();
}
}
}
自定義View 實現一道亮光閃過
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.