之前用58同城app的时候看到它的加载界面不错,但是那时候还不知道如何实现~接触自定义View后,于是自己试着模仿写了一个
先看效果图:

录制的GIF上有一点卡,其实在真机上面运行很流畅的~
其实感觉实现起来并不难,下面说下我的思路,首先是三个形状: 圆、三角、矩形,然后使用动画让它平移达到上升下落的效果,恩差不多~ 开搞
首先在ondraw()开始画
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
cx = getWidth() / 2;
cy = getHeight() / 2;
switch (type) {
case 1:
// 画圆
mPaint.setColor(Color.RED);
canvas.drawCircle(cx, cy, mRadius, mPaint);
break;
case 2:
// 画三角形
mPath.moveTo(cx, cy - mRadius);
mPath.lineTo(cx + mRadius, cy + mRadius);
mPath.lineTo(cx - mRadius, cy + mRadius);
mPaint.setColor(Color.GREEN);
mPath.close();
canvas.drawPath(mPath, mPaint);
break;
case 3:
// 画正方形
RectF.set(cx - mRadius, cy - mRadius, cx + mRadius, cy + mRadius);
mPaint.setColor(Color.YELLOW);
canvas.drawRect(RectF, mPaint);
break;
default:
break;
}
}
是不是很简单啊~ 根据不同的类型画不同的形状(PS:三角形其实没有画好.....数死早)~ 然后传入不同的type画不同的形状,不就实现形状的变换了嘛~ 哦也 第一步完成
但是注意,View只是原地在变换,我们要它动起来!,我这里用动画实现~
public void moveBottom() {
ObjectAnimator animator = ObjectAnimator.ofFloat(this, "translationY",
0, 0 + mBounceHeight);
ObjectAnimator objectAnimator1 = null;
switch (type) {
case 1:// 圆形其实不需要旋转
objectAnimator1 = ObjectAnimator.ofFloat(this, "rotation", 0, -0);
break;
case 2:// 如果是三角形下落旋转120度
objectAnimator1 = ObjectAnimator.ofFloat(this, "rotation", 0, -120);
break;
case 3:// 如果是正方形下落就旋转 90度
objectAnimator1 = ObjectAnimator.ofFloat(this, "rotation", 0, -90);
break;
default:
break;
}
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(animator, objectAnimator1);
animatorSet.setDuration(mDuration);
animatorSet.setInterpolator(new AccelerateInterpolator());// 加速
animatorSet.addListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
moveTop();
if (type == 1) {
scale1();
}
}
@Override
public void onAnimationCancel(Animator animation) {
}
});
animatorSet.start();
}
这里是属性动画~ View向下移动,且加速,移动的同时并且旋转根据不同的类型旋转不同的角度,在动画执行后,再执行平移向上
public void moveTop() {
ObjectAnimator animator = ObjectAnimator.ofFloat(this, "translationY",
mBounceHeight, 0);
ObjectAnimator objectAnimator1 = null;
switch (type) {
case 1:// 圆形其实不需要旋转
objectAnimator1 = ObjectAnimator.ofFloat(this, "rotation", 0, -0);
break;
case 2:// 如果是三角形下落旋转120度
objectAnimator1 = ObjectAnimator.ofFloat(this, "rotation", 0, -120);
break;
case 3:// 如果是正方形下落就旋转 90度
objectAnimator1 = ObjectAnimator.ofFloat(this, "rotation", 0, -90);
break;
default:
break;
}
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(animator, objectAnimator1);
animatorSet.setDuration(mDuration);
animatorSet.setInterpolator(new DecelerateInterpolator());// 减速
animatorSet.addListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
type++;
if (type > 3) {
type = 1;
}
moveBottom();
invalidate();
}
public void onAnimationCancel(Animator animation) {
}
});
animatorSet.start();
}
这个和上面那个差不多,就是执行完之后 换一种Type调用invaludate刷新onDraw方法换一种形状,然后 再执行落下的动画,这就实现了View不断落下升起的效果~
细心的朋友注意到下面那个阴影了,这是怎么实现的呢? 很简单 在球下面放一个ImageView,给一张背景图片,然后执行 缩放动画 X方向(注意:要和View下落和上升保存同步)
ObjectAnimator scaleIndication = ObjectAnimator.ofFloat(mImageView,
"scaleX", 0.5F, 1.5f);
scaleIndication.setDuration(MyProgressView.mDuration);
scaleIndication.start();
scaleIndication.setInterpolator(new AccelerateInterpolator());
scaleIndication.addListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
public void onAnimationRepeat(Animator animation) {
}
public void onAnimationEnd(Animator animation) {
scale1();
}
public void onAnimationCancel(Animator animation) {
}
});
这个是变大,还有一个变小的代码就不贴了,参数换一下就行了,到这里实现的就差不多了~ 有兴趣的同学可以自己试下
是不是很简单啊~ 不过自己觉得还有一些改进的地方,View形状切换方式不够优雅~ 增加一些自定义属性 之类的......