需求:用户点击按钮,切换到播放状态,按钮展示变换背景色效果,展现为呼吸样式.
效果图,如下:
![](https://img.haomeiwen.com/i6533342/5b9ab6d6c22d7b3f.png)
代码:
package com.kaike.la.framework.view.widget;
import android.animation.ArgbEvaluator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.annotation.IntDef;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;
import com.kaike.la.framework.R;
import java.util.ArrayList;
import java.util.List;
import static com.kaike.la.framework.view.widget.BlnPlayView.Status.DEFAULT;
import static com.kaike.la.framework.view.widget.BlnPlayView.Status.PAUSE;
import static com.kaike.la.framework.view.widget.BlnPlayView.Status.PLAY;
/**********************************************************
* @文件名称:BlnPlayView
* @文件作者:lyw
* @创建时间:2018/4/25 11:30
* @文件描述:呼吸效果按钮
* @修改历史:2018/4/25 创建初始版本
**********************************************************/
public class BlnPlayView extends View {
//计算渐变色~~~
private final ArgbEvaluator mArgbEvaluator = new ArgbEvaluator();
private ValueAnimator mAnimator = null;
//渐变色差值~~~
private final List<Integer> mBlnColorResIds = new ArrayList<>();
private final Paint mFunPaint = new Paint();
private final Paint mBgBlnPaint = new Paint();
private Rect mFunRect = null;
private int mCenterX = 0;
private int mCenterY = 0;
//渐变持续时间~~
private int mBlnPeriod = 2000;
//当前该显示默认色~~~
private int mBlnBgDefault = R.color.color_3329305c;
//当前的颜色,渐变色使用~~~
private int mBlnBgCurrent;
private Bitmap mBlnFunDefault = null;
private Bitmap mBlnFunPlay = null;
private Bitmap mBlnFunPause = null;
private int mBlnBgMeasure = 140;
private int mBlnFunMeasure = 52;
//当前状态~~~
private int mMode = Status.PLAY;
public BlnPlayView(Context context) {
this(context, null);
}
public BlnPlayView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public BlnPlayView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initAttrs(context, attrs);
initView();
}
private void initAttrs(Context context, @Nullable AttributeSet attrs) {
final TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.BlnPlayView);
mBlnPeriod = array.getInt(R.styleable.BlnPlayView_blnPeriod, mBlnPeriod);
mBlnBgDefault = array.getResourceId(R.styleable.BlnPlayView_blnBgDefault, mBlnBgDefault);
mBlnFunDefault = BitmapFactory.decodeResource(getResources(), array.getResourceId(R.styleable.BlnPlayView_blnFunDrawableDefault, R.drawable.ic_fun_asr_play_default_cyan));
mBlnFunPlay = BitmapFactory.decodeResource(getResources(), array.getResourceId(R.styleable.BlnPlayView_blnFunPlayDrawable, R.drawable.ic_fun_asr_play_cyan));
mBlnFunPause = BitmapFactory.decodeResource(getResources(), array.getResourceId(R.styleable.BlnPlayView_blnFunPauseDrawable, R.drawable.ic_fun_asr_pause_cyan));
mBlnBgMeasure = array.getDimensionPixelSize(R.styleable.BlnPlayView_blnBgMeasure, mBlnBgMeasure);
mBlnFunMeasure = array.getDimensionPixelSize(R.styleable.BlnPlayView_blnFunMeasure, mBlnFunMeasure);
array.recycle();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
resetCondition();
}
@Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
if (hasWindowFocus) {
if (Status.DEFAULT == getMode()) {
showDefault();
} else if (Status.PAUSE == getMode()) {
showPause();
} else {
showPlay();
}
} else {
resetCondition();
}
}
/**
* 初始化相关数据~~~
*/
private void initView() {
//设置默认渐变色~~~
initBlnColor();
//初始化paint~~
initPaints();
}
/**
* 初始化 paint
*/
private void initPaints() {
mFunPaint.setAntiAlias(true);
mFunPaint.setFlags(Paint.FILTER_BITMAP_FLAG);
mBgBlnPaint.setAntiAlias(true);
mBgBlnPaint.setStyle(Paint.Style.FILL);
}
//初始化渐变色~~~
private void initBlnColor() {
mBlnColorResIds.add(R.color.color_29305C);
mBlnColorResIds.add(R.color.color_37417A);
mBlnColorResIds.add(R.color.color_29305C);
mBlnBgCurrent = ContextCompat.getColor(getContext(), mBlnColorResIds.get(0));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = measureDimension(mBlnBgMeasure, widthMeasureSpec);
int height = measureDimension(mBlnBgMeasure, heightMeasureSpec);
setMeasuredDimension(width, height);
}
public int measureDimension(int defaultSize, int measureSpec) {
int result;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
// 父结点要求其子节点的大小指定为某个确切的值。其子节点以及其他子孙结点都需要适应该大小
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
//父结点对子结点的大小没有任何要求
result = defaultSize; //UNSPECIFIED
if (specMode == MeasureSpec.AT_MOST) {
//父结点要求其子节点的大小不能超过某个最大值,其子节点以及其他子孙结点的大小都需要小于这个值
result = Math.min(result, specSize);
}
}
return result;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
mCenterX = (getWidth() + getPaddingLeft() - getPaddingRight()) / 2;
mCenterY = (getHeight() + getPaddingTop() - getPaddingBottom()) / 2;
mFunRect = new Rect(mCenterX - mBlnFunMeasure / 2,
mCenterY - mBlnFunMeasure / 2,
mCenterX + mBlnFunMeasure / 2,
mCenterY + mBlnFunMeasure / 2);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//绘制~~~
switch (getMode()) {
case DEFAULT:
drawDefault(canvas);
break;
case PAUSE:
drawPause(canvas);
break;
case PLAY:
drawPlay(canvas);
break;
}
}
/**
* 绘制 渐变色背景,暂停按钮~~~
*/
private void drawPlay(Canvas canvas) {
drawCircleBg(canvas, false);
drawablePlay(canvas, false);
}
/**
* 绘制背景,播放按钮~~~
*/
private void drawPause(Canvas canvas) {
drawCircleBg(canvas, false);
drawablePause(canvas);
}
/**
* 绘制 背景,暂停按钮~~~ 不可点击状态~~~
*/
private void drawDefault(Canvas canvas) {
drawCircleBg(canvas, true);
drawablePlay(canvas, true);
}
/**
* 绘制暂停按钮~~~
*
* @param canvas
*/
private void drawablePause(Canvas canvas) {
canvas.drawBitmap(mBlnFunPause, null, mFunRect, mFunPaint);
}
/**
* 绘制播放按钮~~~
*
* @param canvas
* @param isDefault
*/
private void drawablePlay(Canvas canvas, boolean isDefault) {
if (isDefault) {
canvas.drawBitmap(mBlnFunDefault, null, mFunRect, mFunPaint);
} else {
canvas.drawBitmap(mBlnFunPlay, null, mFunRect, mFunPaint);
}
}
/**
* 绘制原型背景~~~
*
* @param canvas
* @param isDefault
*/
private void drawCircleBg(Canvas canvas, boolean isDefault) {
if (isDefault) {
//不可使用时,设置为默认色~~~
mBgBlnPaint.setColor(ContextCompat.getColor(getContext(), mBlnBgDefault));
} else {
//可以使用,显示为渐变色的第一个色值~~~
mBgBlnPaint.setColor(mBlnBgCurrent);
}
canvas.drawCircle(mCenterX, mCenterY, mBlnBgMeasure / 2, mBgBlnPaint);
}
/**
* 显示默认状态~~~
*/
public void showDefault() {
resetCondition();
this.mMode = Status.DEFAULT;
invalidate();
}
/**
* 显示暂停~~~
*/
public void showPause() {
resetCondition();
this.mMode = Status.PAUSE;
showBln();
}
/**
* 显示播放~~~
*/
public void showPlay() {
resetCondition();
this.mMode = Status.PLAY;
invalidate();
}
/**
* 启动定时器~~~
*/
private void showBln() {
mAnimator = ValueAnimator.ofInt(0, (mBlnColorResIds.size() - 1) * 10);
mAnimator.setDuration(mBlnPeriod);
mAnimator.setRepeatCount(ValueAnimator.INFINITE);
mAnimator.setRepeatMode(ValueAnimator.RESTART);
mAnimator.setInterpolator(new LinearInterpolator());
mAnimator.addUpdateListener(updateListener);
mAnimator.start();
}
/**
* 初始化相关状态~~~
*/
private void resetCondition() {
//恢复相关变量初始值~~~
mBlnBgCurrent = ContextCompat.getColor(getContext(), mBlnColorResIds.get(0));
if (null != mAnimator) {
mAnimator.cancel();
mAnimator = null;
}
}
/**
* 设置渐变色数据数组
*/
public void setBlnColors(List<Integer> blnColorResIds) {
if (null == blnColorResIds || blnColorResIds.isEmpty()) {
return;
}
this.mBlnColorResIds.clear();
this.mBlnColorResIds.addAll(blnColorResIds);
mBlnBgCurrent = ContextCompat.getColor(getContext(), mBlnColorResIds.get(0));
}
/**
* 设置 渐变持续时间~~~
*
* @param second
*/
public void setBlnPeriod(int second) {
if (second < 0) {
mBlnPeriod = 1000;
} else {
mBlnPeriod = second;
}
}
/**
* 获取当前的mode
*
* @return
*/
public int getMode() {
return mMode;
}
private ValueAnimator.AnimatorUpdateListener updateListener = new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//0-100~~~
final int value = (int) animation.getAnimatedValue();
//求余数~~~
final int remainder = value % 10;
//求商~~~
final int quotient = value / 10;
final float fraction = remainder / 10.0f;
final int start = ContextCompat.getColor(getContext(), mBlnColorResIds.get(quotient));
final int end = ContextCompat.getColor(getContext(), mBlnColorResIds.get(quotient + 1));
//计算对应的颜色~~~
mBlnBgCurrent = (int) (mArgbEvaluator.evaluate(fraction, start, end));
invalidate();
}
};
@IntDef({DEFAULT, PAUSE, PLAY})
@interface Status {
//默认状态~~~
int DEFAULT = 0;
//暂停状态~~~
int PAUSE = 1;
//播放状态~~~
int PLAY = 2;
}
}
网友评论