2019独角兽企业重金招聘Python工程师标准>>>
好久没有分享些什么了,闲来无事看了一下apidemo ,于是自己练手, 给大家分享一个通过Animator 实现弹跳的篮球的效果.
我们可以把这动画拆解为3个动画
1.小球落下
2.小球形变(包括小球变宽,变矮)
3.小球上升
小球的落下和上升没什么好说的
实现如下
//小球落下
ValueAnimator downAnimator = ObjectAnimator.ofFloat(mShapeHolder, "y", startY , endY);
downAnimator.setDuration(duration);
downAnimator.setInterpolator(new AccelerateInterpolator());
downAnimator.addUpdateListener(this);
//小球上升
ValueAnimator upAnimator = ObjectAnimator.ofFloat(mShapeHolder, "y", endY, startY);
upAnimator.setDuration(duration);
upAnimator.setInterpolator(new DecelerateInterpolator());
upAnimator.addUpdateListener(this);
那么难点就是小球的形变了
如果想用animator实现小球的形变,我将其分解为了四个部分
1.小球的变宽
2.小球在变宽的时候的x居中
3.小球的变矮
4.小球在变矮时候的y居中
分析ok了就可以编码了
// 1.设置小球的宽度变大
ValueAnimator makeBallWide = ObjectAnimator.ofFloat(mShapeHolder, "width", mShapeHolder.getWidth(),
mShapeHolder.getWidth() + BALLHEIGH/2); //改变的是mShapeHolder中width的属性值
makeBallWide.setDuration(duration/4);
//重复一次
makeBallWide.setRepeatCount(1);
//在重复另一次的时候回到原来的状态
makeBallWide.setRepeatMode(ValueAnimator.REVERSE);
makeBallWide.setInterpolator(new DecelerateInterpolator());
// 2.在小球变扁的时候 需要让他居中
ValueAnimator centerAnimator = ObjectAnimator.ofFloat(mShapeHolder, "x", mShapeHolder.getX(),
mShapeHolder.getX() - BALLHEIGH/4);
centerAnimator.setDuration(duration/4);
centerAnimator.setRepeatCount(1);
centerAnimator.setRepeatMode(ValueAnimator.REVERSE);
centerAnimator.setInterpolator(new DecelerateInterpolator());
centerAnimator.addUpdateListener(this);
//3. 小球高度的变小
ValueAnimator makeBallLow = ObjectAnimator.ofFloat(mShapeHolder, "height",
mShapeHolder.getHeight(), mShapeHolder.getHeight() - BALLHEIGH/4);
makeBallLow.setDuration(duration/4);
makeBallLow.setRepeatCount(1);
makeBallLow.setInterpolator(new DecelerateInterpolator());
makeBallLow.setRepeatMode(ValueAnimator.REVERSE);
//4.小球高度变化时y的居中
ValueAnimator yWhenBallisPlan = ObjectAnimator.ofFloat(mShapeHolder, "y", endY, endY + BALLHEIGH/3);
yWhenBallisPlan.setDuration(duration/4);
yWhenBallisPlan.setRepeatCount(1);
yWhenBallisPlan.setInterpolator(new DecelerateInterpolator());
yWhenBallisPlan.setRepeatMode(ValueAnimator.REVERSE);
全部代码:
public class MainActivity extends Activity {
private ShapeHolder mShapeHolder;
private final float BALLHEIGH = 100f;
@SuppressWarnings("deprecation")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.bouncing_balls);
int screenWidth = getWindowManager().getDefaultDisplay().getWidth();
LinearLayout container = (LinearLayout) findViewById(R.id.container);
mShapeHolder = addBall(screenWidth/2, 100);
final MyAnimationView myAnimationView = new MyAnimationView(this);
container.addView(myAnimationView);
myAnimationView.post(new Runnable() {
@Override
public void run() {
myAnimationView.showBall();
}
});
}
public class MyAnimationView extends View implements AnimatorUpdateListener {
public final ArrayList balls = new ArrayList();
AnimatorSet animation = null;
public MyAnimationView(Context context) {
super(context);
}
public void showBall() {
float startY = mShapeHolder.getY();
float endY = getHeight() - BALLHEIGH;
long duration = 1000;
//小球落下
ValueAnimator downAnimator = ObjectAnimator.ofFloat(mShapeHolder, "y", startY , endY);
downAnimator.setDuration(duration);
downAnimator.setInterpolator(new AccelerateInterpolator());
//每次都需要添加这个监听刷新UI 否则不能看到动画
downAnimator.addUpdateListener(this);
// 1.设置小球的宽度变大
ValueAnimator makeBallWide = ObjectAnimator.ofFloat(mShapeHolder, "width", mShapeHolder.getWidth(),
mShapeHolder.getWidth() + BALLHEIGH/2);
makeBallWide.setDuration(duration/4);
//重复一次
makeBallWide.setRepeatCount(1);
//在重复另一次的时候回到原来的状态
makeBallWide.setRepeatMode(ValueAnimator.REVERSE);
makeBallWide.setInterpolator(new DecelerateInterpolator());
// 2.在小球变扁的时候 需要让他居中
ValueAnimator centerAnimator = ObjectAnimator.ofFloat(mShapeHolder, "x", mShapeHolder.getX(),
mShapeHolder.getX() - BALLHEIGH/4);
centerAnimator.setDuration(duration/4);
centerAnimator.setRepeatCount(1);
centerAnimator.setRepeatMode(ValueAnimator.REVERSE);
centerAnimator.setInterpolator(new DecelerateInterpolator());
centerAnimator.addUpdateListener(this);
//3. 小球高度的变小
ValueAnimator makeBallLow = ObjectAnimator.ofFloat(mShapeHolder, "height",
mShapeHolder.getHeight(), mShapeHolder.getHeight() - BALLHEIGH/4);
makeBallLow.setDuration(duration/4);
makeBallLow.setRepeatCount(1);
makeBallLow.setInterpolator(new DecelerateInterpolator());
makeBallLow.setRepeatMode(ValueAnimator.REVERSE);
//4.小球高度变化时y的居中
ValueAnimator yWhenBallisPlan = ObjectAnimator.ofFloat(mShapeHolder, "y", endY, endY + BALLHEIGH/3);
yWhenBallisPlan.setDuration(duration/4);
yWhenBallisPlan.setRepeatCount(1);
yWhenBallisPlan.setInterpolator(new DecelerateInterpolator());
yWhenBallisPlan.setRepeatMode(ValueAnimator.REVERSE);
//小球上升
ValueAnimator upAnimator = ObjectAnimator.ofFloat(mShapeHolder, "y", endY, startY);
upAnimator.setDuration(duration);
upAnimator.setInterpolator(new DecelerateInterpolator());
upAnimator.addUpdateListener(this);
final AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(downAnimator).before(centerAnimator);
animatorSet.playTogether(centerAnimator , makeBallWide ,makeBallLow, yWhenBallisPlan);
animatorSet.play(upAnimator).after(centerAnimator);
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
animatorSet.start();
super.onAnimationEnd(animation);
}
});
animatorSet.start();
}
@Override
protected void onDraw(Canvas canvas) {
canvas.save();
canvas.translate(mShapeHolder.getX(), mShapeHolder.getY());
mShapeHolder.getShape().draw(canvas);
canvas.restore();
}
@Override
public void onAnimationUpdate(ValueAnimator arg0) {
invalidate();
}
}
private ShapeHolder addBall(float x, float y) {
OvalShape circle = new OvalShape();
circle.resize(BALLHEIGH, BALLHEIGH);
ShapeDrawable drawable = new ShapeDrawable(circle);
ShapeHolder shapeHolder = new ShapeHolder(drawable);
shapeHolder.setX(x - BALLHEIGH/2);
shapeHolder.setY(y - BALLHEIGH/2);
int red = (int)(Math.random() * 255);
int green = (int)(Math.random() * 255);
int blue = (int)(Math.random() * 255);
int color = 0xff000000 | red << 16 | green << 8 | blue;
Paint paint = drawable.getPaint(); //new Paint(Paint.ANTI_ALIAS_FLAG);
int darkColor = 0xff000000 | red/4 << 16 | green/4 << 8 | blue/4;
RadialGradient gradient = new RadialGradient(37.5f, 12.5f,
50f, color, darkColor, Shader.TileMode.CLAMP);
paint.setShader(gradient);
shapeHolder.setPaint(paint);
return shapeHolder;
}
}
附件 http://www.eoeandroid.com/forum.php?mod=viewthread&tid=311392&page=1&extra=#pid3285053