代码github,感兴趣的可以一起研究下。为了避免你们没有兴趣看下去,先来一张效果图吧
大体思路:
首先经过观察发现,ofo开锁效果由几个半径不断变化的圆构成,并且圆的颜色的透明度随着半径的不断增大逐渐透明;之余中间的文字的话由于这里不涉及到具体的业务与数据流,所以就通过ValueAnimator不断改变进度,重绘就好了。
关键代码解析:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int specWidthMode = MeasureSpec.getMode(widthMeasureSpec);
int specWidthSize = MeasureSpec.getSize(widthMeasureSpec);
int specHeightMode = MeasureSpec.getMode(heightMeasureSpec);
int specHeightSize = MeasureSpec.getSize(heightMeasureSpec);
if (specWidthMode == MeasureSpec.AT_MOST) {
//宽为wrap_content
mWidth = DEFAULT_WIDTH;
} else {
mWidth = specWidthSize;
}
if (specHeightMode == MeasureSpec.AT_MOST) {
//高为wrap_content
mHeight = DEFAULT_HEIGHT;
} else {
mHeight = specHeightSize;
}
setMeasuredDimension(mWidth, mHeight);
initCircles();
}复制代码
当控件的宽或者高为wrap_content时,给定一个600的默认值,取宽高的较小者作为最大圆的直径。
class Circle {
long mCreateTime;
public @ColorInt
int mColor;
//最大半径
public Circle(long circleTime) {
mCreateTime = circleTime;
}
public int getCurrentRadius() {
float percent = (System.currentTimeMillis() - mCreateTime) % LIFE_DURATION * 1.0f / LIFE_DURATION;
mColor = ColorUtils.setAlphaComponent(mCircleColor, (int) ((1 - percent) * 255));
return (int) (percent * mMaxRadius);
}
public @ColorInt
int getColor() {
return mColor;
}
}复制代码
Circle抽象了圆的类型,封装了圆当前的半径以及颜色,由于圆的半径和颜色随着时间的变化而变化规则是与一个常数取模运算在除以常数获得一个从0到1再到0重复变化的值,从而觉得当前圆的半径大小以及颜色。
private void initCircles() {
if (mCircles != null) return;
if (mMaxRadius <= 0) {
mMaxRadius = Math.min(mWidth - getPaddingLeft() - getPaddingRight(), mHeight - getPaddingTop() - getPaddingBottom()) / 2;
}
int count = LIFE_DURATION / STEP;
mCircles = new ArrayList<>();
long currentTime = System.currentTimeMillis() - LIFE_DURATION;
for (int i = 0; i < count; i++) {
mCircles.add(new Circle(currentTime + i * STEP));
}
}复制代码
注意STEP这个常量,表示的是相邻的圆间隔的时间,从而产生颜色以及半径的不同。如果需要圆更加密集把值改小就行。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (Circle cirCle : mCircles) {
drawCircle(canvas, cirCle);
}
drawText(canvas);
if (mIsRun){
invalidate();
}
}复制代码
通过在onDraw()里面调用invalidate()方法在进度没有达到100时不断重绘,形成波纹扩散的效果。
代码地址github对你有帮助的话顺手给个星吧,反正不会怀孕!