會閃光的按鈕Button和圖片ImageView,ProgressBar進度條顏色閃動
阿新 • • 發佈:2019-02-18
模仿發光文字做了個會發光的按鈕,效果如下
原理很簡單,就是在view的基礎上畫一道白色漸變表示亮光,移動亮光位置形成閃光動畫
下面貼程式碼
public class ShanView extends TextView {
// private LinearGradient mLinearGradient;
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;
public ShanView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public ShanView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ShanView(Context context) {
super(context);
init();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int w = getMeasuredWidth();
int h = getMeasuredHeight();
rect = new Rect(0, 0, w, h);
}
private Rect rect;
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (mViewWidth == 0) {
mViewWidth = getMeasuredWidth();
mViewHeight = getMeasuredHeight();
if (mViewWidth > 0) {
mPaint = new Paint();
//亮光閃過
mGradient = new LinearGradient(0, 0, mViewWidth, mViewHeight, new int[]{0x00ffffff, 0x55ffffff,
0x00ffffff}, new float[]{0, 0.9f, 1}, Shader.TileMode.CLAMP);
//暗色
// mGradient = new LinearGradient(0, 0, mViewWidth, mViewHeight, new int[]{0x00000000, 0x55000000,
// 0x00000000}, new float[]{0, 0.9f, 1}, Shader.TileMode.CLAMP);
//用暗色凸顯亮亮光(不好用)
// mGradient = new LinearGradient(0, 0, mViewWidth, mViewHeight, new int[]{0x33000000, 0x00000000, 0x00ffffff, 0x88ffffff,
//0x00ffffff, 0x00000000, 0x33000000}, new float[]{0, 0.3f, 0.3f, 0.58f, 0.7f, 0.7f, 1}, Shader.TileMode.CLAMP);
mPaint.setShader(mGradient);
mPaint.setXfermode(new PorterDuffXfermode(Mode.LIGHTEN));
mGradientMatrix = new Matrix();
mGradientMatrix.setTranslate(-2 * mViewWidth, mViewHeight);
mGradient.setLocalMatrix(mGradientMatrix);
rect = new Rect(0, 0, w, h);
}
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mAnimating && mGradientMatrix != null) {
canvas.drawRect(rect, mPaint);
}
}
private ValueAnimator valueAnimator;
private void init() {
initValueAnimator();
}
private void initValueAnimator() {
valueAnimator = ValueAnimator.ofFloat(0, 1);
valueAnimator.setDuration(6000);
valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
valueAnimator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float v = (Float) animation.getAnimatedValue();
mTranslateX = 4 * mViewWidth * v - mViewWidth * 2;
mTranslateY = mViewHeight * v;
mGradientMatrix.setTranslate(mTranslateX, mTranslateY);
mGradient.setLocalMatrix(mGradientMatrix);
invalidate();
}
});
if (autoRun)
getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
getViewTreeObserver().removeGlobalOnLayoutListener(this);
mAnimating = true;
valueAnimator.start();
}
});
}
//是否自動執行動畫
private boolean autoRun = true;
public void setAutoRun(boolean autoRun) {
this.autoRun = autoRun;
}
//停止動畫
public void pause() {
if (mAnimating) {
mAnimating = false;
valueAnimator.cancel();
invalidate();
}
}
//重新開始動畫
public void resume() {
if (!mAnimating) {
mAnimating = true;
valueAnimator = ValueAnimator.ofFloat(0, 1);
valueAnimator.setDuration(6000);
valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
valueAnimator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float v = (Float) animation.getAnimatedValue();
mTranslateX = 4 * mViewWidth * v - mViewWidth * 2;
mTranslateY = mViewHeight * v;
mGradientMatrix.setTranslate(mTranslateX, mTranslateY);
mGradient.setLocalMatrix(mGradientMatrix);
invalidate();
}
});
valueAnimator.start();
}
}
}
可以改為繼承其他View比如ImageView
可以用在ProgressBar上,只繪製有進度部分的顏色閃光.
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(0x00ffffff);
int saveCount = canvas.saveLayer(rect, mPaint, Canvas.ALL_SAVE_FLAG);
if (mAnimating && mGradientMatrix != null) {
rect.right = mProgresWidth = (float) getProgress() / getMax() * mViewWidth;
canvas.drawRect(rect, mPaint);
}
canvas.restoreToCount(saveCount);
}
換用了黑色的漸變
//暗色
mGradient=new LinearGradient(0, 0, 0, mViewHeight, new int[]0x00000000, 0x55000000,
0x00000000}, new float[]{0, 0.9f, 1}, Shader.TileMode.CLAMP);
改進度條風格的辦法,在drawble下新建一個xml檔案,設定為該進度條的progressDrawable
一級和二級進度條的clip一定要有,否則進度條就像背景一樣全部顯示了
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- 設定背景色影象資源 -->
<item android:id="@android:id/background">
<shape>
<corners android:radius="10dp" />
<solid android:color="#ffeeeeee" />
</shape>
</item>
<!-- 設定第二級進度條顏色影象資源 -->
<item android:id="@android:id/secondaryProgress">
<clip>
<shape>
<corners android:radius="10dp" />
<solid android:color="#880000ff" />
</shape>
</clip>
</item>
<!-- 設定第一級進度條顏色影象資源 -->
<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="10dp" />
<solid android:color="#880000ff" />
</shape>
</clip>
</item>
</layer-list>
進度條本身的進度動畫就省略不提了