- 效果图:
- 应用场景:可以用到上下拉刷新的动画
- 分析:
1.前半段横加速度减速运动
2.后半段横加速度加速运动
3.且可以有多个圆点
4.每个圆点出发时间有延迟
- 实现
首先当然的onMeasure();
/**
* 测试view高度
* 1、如果设置了绝对值,则高度即为设置的高度
* 2、如果没有设置绝对值, 则高度设置为圆点直径+2
* 3、如果设置了wrap-content 则跟(圆点直径+2)比较 谁小采用谁
*
* MeasureSpec.EXACTLY 给控件设置的有确切的值
* MeasureSpec.UNSPECIFIED
* MeasureSpec.AT_MOST wrap-content
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int wSize = MeasureSpec.getSize(widthMeasureSpec);
int hMode = MeasureSpec.getMode(heightMeasureSpec);
int hSize = MeasureSpec.getSize(heightMeasureSpec);
//测量高度,宽度不做处理
if (hMode == MeasureSpec.EXACTLY) {
mHeight = hSize;
} else {
mHeight = (int) (mDotRadius * 2 + 2);
if (hMode == MeasureSpec.AT_MOST) {
mHeight = Math.min(mHeight, hSize);
}
}
setMeasuredDimension(wSize, mHeight);
}
其次需要考虑当界面发生变化时,
/**
* view宽高发生动态的变化
* @param w 新的width
* @param h 新的height
* @param oldw 原本的width
* @param oldh 原本的height
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
//给view高度 赋予最新的高度值
mHeight = h;
//给小球总位移 赋予最新的值
mDisplacement = w;
//设置初始速度为:宽度除于小球运动周期
v0 = 2 * mDisplacement / mPeriod;
// 设置加速度
a = 2 * v0 / mPeriod;
//每个小圆点进入边界的延迟时间
timeInterval = mPeriod/(mDotNum*2) + mDotNum;
}
下边开始画:
private void init() {
mPaint = new Paint();
//设置画笔颜色
mPaint.setColor(mDotColor);
//全部填充
mPaint.setStyle(Paint.Style.FILL);
//抗锯齿
mPaint.setAntiAlias(true);
//初始化圆点X坐标的集合
cxArr = new float[mDotNum];
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (animator == null) {
startMotion();
}
//draw圆点
drawDot(canvas);
}
开启动画:
/**
* 开启动画
*/
private void startMotion() {
animator = ValueAnimator.ofFloat(0f, 140f);
animator.setDuration(mPeriod).setRepeatCount(ValueAnimator.INFINITE);
animator.setInterpolator(new LinearInterpolator());//使用线性插值器
animator.start();
animator.addUpdateListener(
new ValueAnimator.AnimatorUpdateListener() {
@Overri