很久沒有分享些什麼了,閒來無事看了一下apidemo ,因而本身練手, 給你們分享一個經過Animator 實現彈跳的籃球的效果.
php
咱們能夠把這動畫拆解爲3個動畫
1.小球落下
2.小球形變(包括小球變寬,變矮)
3.小球上升 java
小球的落下和上升沒什麼好說的 android
實現以下 canvas
//小球落下 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);
那麼難點就是小球的形變了 api
若是想用animator實現小球的形變,我將其分解爲了四個部分
1.小球的變寬
2.小球在變寬的時候的x居中
3.小球的變矮
4.小球在變矮時候的y居中 dom
分析ok了就能夠編碼了 ide
// 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);
所有代碼: post
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<ShapeHolder> balls = new ArrayList<ShapeHolder>(); 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 動畫