Home | History | Annotate | Download | only in animation
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.example.android.apis.animation;
     18 
     19 // Need the following import to get access to the app resources, since this
     20 // class is in a sub-package.
     21 import android.graphics.drawable.ColorDrawable;
     22 import com.example.android.apis.R;
     23 
     24 import android.animation.*;
     25 import android.app.Activity;
     26 import android.content.Context;
     27 import android.graphics.Canvas;
     28 import android.graphics.Paint;
     29 import android.graphics.RadialGradient;
     30 import android.graphics.Shader;
     31 import android.graphics.drawable.ShapeDrawable;
     32 import android.graphics.drawable.shapes.OvalShape;
     33 import android.os.Bundle;
     34 import android.view.MotionEvent;
     35 import android.view.View;
     36 import android.view.animation.AccelerateInterpolator;
     37 import android.view.animation.DecelerateInterpolator;
     38 import android.widget.LinearLayout;
     39 
     40 import java.util.ArrayList;
     41 
     42 
     43 public class BouncingBalls extends Activity {
     44     /** Called when the activity is first created. */
     45     @Override
     46     public void onCreate(Bundle savedInstanceState) {
     47         super.onCreate(savedInstanceState);
     48         setContentView(R.layout.bouncing_balls);
     49         LinearLayout container = (LinearLayout) findViewById(R.id.container);
     50         container.addView(new MyAnimationView(this));
     51     }
     52 
     53     public class MyAnimationView extends View {
     54 
     55         private static final int RED = 0xffFF8080;
     56         private static final int BLUE = 0xff8080FF;
     57         private static final int CYAN = 0xff80ffff;
     58         private static final int GREEN = 0xff80ff80;
     59 
     60         public final ArrayList<ShapeHolder> balls = new ArrayList<ShapeHolder>();
     61         AnimatorSet animation = null;
     62 
     63         public MyAnimationView(Context context) {
     64             super(context);
     65 
     66             // Animate background color
     67             // Note that setting the background color will automatically invalidate the
     68             // view, so that the animated color, and the bouncing balls, get redisplayed on
     69             // every frame of the animation.
     70             ValueAnimator colorAnim = ObjectAnimator.ofInt(this, "backgroundColor", RED, BLUE);
     71             colorAnim.setDuration(3000);
     72             colorAnim.setEvaluator(new ArgbEvaluator());
     73             colorAnim.setRepeatCount(ValueAnimator.INFINITE);
     74             colorAnim.setRepeatMode(ValueAnimator.REVERSE);
     75             colorAnim.start();
     76         }
     77 
     78         @Override
     79         public boolean onTouchEvent(MotionEvent event) {
     80             if (event.getAction() != MotionEvent.ACTION_DOWN &&
     81                     event.getAction() != MotionEvent.ACTION_MOVE) {
     82                 return false;
     83             }
     84             ShapeHolder newBall = addBall(event.getX(), event.getY());
     85 
     86             // Bouncing animation with squash and stretch
     87             float startY = newBall.getY();
     88             float endY = getHeight() - 50f;
     89             float h = (float)getHeight();
     90             float eventY = event.getY();
     91             int duration = (int)(500 * ((h - eventY)/h));
     92             ValueAnimator bounceAnim = ObjectAnimator.ofFloat(newBall, "y", startY, endY);
     93             bounceAnim.setDuration(duration);
     94             bounceAnim.setInterpolator(new AccelerateInterpolator());
     95             ValueAnimator squashAnim1 = ObjectAnimator.ofFloat(newBall, "x", newBall.getX(),
     96                     newBall.getX() - 25f);
     97             squashAnim1.setDuration(duration/4);
     98             squashAnim1.setRepeatCount(1);
     99             squashAnim1.setRepeatMode(ValueAnimator.REVERSE);
    100             squashAnim1.setInterpolator(new DecelerateInterpolator());
    101             ValueAnimator squashAnim2 = ObjectAnimator.ofFloat(newBall, "width", newBall.getWidth(),
    102                     newBall.getWidth() + 50);
    103             squashAnim2.setDuration(duration/4);
    104             squashAnim2.setRepeatCount(1);
    105             squashAnim2.setRepeatMode(ValueAnimator.REVERSE);
    106             squashAnim2.setInterpolator(new DecelerateInterpolator());
    107             ValueAnimator stretchAnim1 = ObjectAnimator.ofFloat(newBall, "y", endY,
    108                     endY + 25f);
    109             stretchAnim1.setDuration(duration/4);
    110             stretchAnim1.setRepeatCount(1);
    111             stretchAnim1.setInterpolator(new DecelerateInterpolator());
    112             stretchAnim1.setRepeatMode(ValueAnimator.REVERSE);
    113             ValueAnimator stretchAnim2 = ObjectAnimator.ofFloat(newBall, "height",
    114                     newBall.getHeight(), newBall.getHeight() - 25);
    115             stretchAnim2.setDuration(duration/4);
    116             stretchAnim2.setRepeatCount(1);
    117             stretchAnim2.setInterpolator(new DecelerateInterpolator());
    118             stretchAnim2.setRepeatMode(ValueAnimator.REVERSE);
    119             ValueAnimator bounceBackAnim = ObjectAnimator.ofFloat(newBall, "y", endY,
    120                     startY);
    121             bounceBackAnim.setDuration(duration);
    122             bounceBackAnim.setInterpolator(new DecelerateInterpolator());
    123             // Sequence the down/squash&stretch/up animations
    124             AnimatorSet bouncer = new AnimatorSet();
    125             bouncer.play(bounceAnim).before(squashAnim1);
    126             bouncer.play(squashAnim1).with(squashAnim2);
    127             bouncer.play(squashAnim1).with(stretchAnim1);
    128             bouncer.play(squashAnim1).with(stretchAnim2);
    129             bouncer.play(bounceBackAnim).after(stretchAnim2);
    130 
    131             // Fading animation - remove the ball when the animation is done
    132             ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
    133             fadeAnim.setDuration(250);
    134             fadeAnim.addListener(new AnimatorListenerAdapter() {
    135                 @Override
    136                 public void onAnimationEnd(Animator animation) {
    137                     balls.remove(((ObjectAnimator)animation).getTarget());
    138 
    139                 }
    140             });
    141 
    142             // Sequence the two animations to play one after the other
    143             AnimatorSet animatorSet = new AnimatorSet();
    144             animatorSet.play(bouncer).before(fadeAnim);
    145 
    146             // Start the animation
    147             animatorSet.start();
    148 
    149             return true;
    150         }
    151 
    152         private ShapeHolder addBall(float x, float y) {
    153             OvalShape circle = new OvalShape();
    154             circle.resize(50f, 50f);
    155             ShapeDrawable drawable = new ShapeDrawable(circle);
    156             ShapeHolder shapeHolder = new ShapeHolder(drawable);
    157             shapeHolder.setX(x - 25f);
    158             shapeHolder.setY(y - 25f);
    159             int red = (int)(Math.random() * 255);
    160             int green = (int)(Math.random() * 255);
    161             int blue = (int)(Math.random() * 255);
    162             int color = 0xff000000 | red << 16 | green << 8 | blue;
    163             Paint paint = drawable.getPaint(); //new Paint(Paint.ANTI_ALIAS_FLAG);
    164             int darkColor = 0xff000000 | red/4 << 16 | green/4 << 8 | blue/4;
    165             RadialGradient gradient = new RadialGradient(37.5f, 12.5f,
    166                     50f, color, darkColor, Shader.TileMode.CLAMP);
    167             paint.setShader(gradient);
    168             shapeHolder.setPaint(paint);
    169             balls.add(shapeHolder);
    170             return shapeHolder;
    171         }
    172 
    173         @Override
    174         protected void onDraw(Canvas canvas) {
    175             for (int i = 0; i < balls.size(); ++i) {
    176                 ShapeHolder shapeHolder = balls.get(i);
    177                 canvas.save();
    178                 canvas.translate(shapeHolder.getX(), shapeHolder.getY());
    179                 shapeHolder.getShape().draw(canvas);
    180                 canvas.restore();
    181             }
    182         }
    183     }
    184 }