1b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase/* 2b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase * Copyright (C) 2010 The Android Open Source Project 3b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase * 4b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase * Licensed under the Apache License, Version 2.0 (the "License"); 5b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase * you may not use this file except in compliance with the License. 6b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase * You may obtain a copy of the License at 7b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase * 8b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase * http://www.apache.org/licenses/LICENSE-2.0 9b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase * 10b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase * Unless required by applicable law or agreed to in writing, software 11b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase * distributed under the License is distributed on an "AS IS" BASIS, 12b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase * See the License for the specific language governing permissions and 14b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase * limitations under the License. 15b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase */ 16b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase 17b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haasepackage com.example.android.apis.animation; 18b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase 19b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase// Need the following import to get access to the app resources, since this 20b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase// class is in a sub-package. 21d9855a8dbed211de6e1c1cf55e20201349c40432Chet Haaseimport android.animation.Animator; 22b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haaseimport com.example.android.apis.R; 23b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase 24b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haaseimport java.util.ArrayList; 25b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase 26d9855a8dbed211de6e1c1cf55e20201349c40432Chet Haaseimport android.animation.ValueAnimator; 27d9855a8dbed211de6e1c1cf55e20201349c40432Chet Haaseimport android.animation.ObjectAnimator; 28d9855a8dbed211de6e1c1cf55e20201349c40432Chet Haaseimport android.animation.AnimatorSet; 29b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haaseimport android.app.Activity; 30b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haaseimport android.content.Context; 31b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haaseimport android.graphics.Canvas; 32b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haaseimport android.graphics.Paint; 33b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haaseimport android.graphics.RadialGradient; 34b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haaseimport android.graphics.Shader; 35b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haaseimport android.graphics.drawable.ShapeDrawable; 36b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haaseimport android.graphics.drawable.shapes.OvalShape; 37b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haaseimport android.os.Bundle; 38b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haaseimport android.view.View; 39b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haaseimport android.view.animation.BounceInterpolator; 40b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haaseimport android.widget.Button; 41b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haaseimport android.widget.LinearLayout; 42b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haaseimport android.widget.SeekBar; 43b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase 44b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase/** 45d9855a8dbed211de6e1c1cf55e20201349c40432Chet Haase * This application demonstrates the seeking capability of ValueAnimator. The SeekBar in the 46b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase * UI allows you to set the position of the animation. Pressing the Run button will play from 47b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase * the current position of the animation. 48b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase */ 49b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haasepublic class AnimationSeeking extends Activity { 50b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase 51b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase private static final int DURATION = 1500; 52b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase private SeekBar mSeekBar; 53b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase 54b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase /** Called when the activity is first created. */ 55b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase @Override 56b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase public void onCreate(Bundle savedInstanceState) { 57b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase super.onCreate(savedInstanceState); 58b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase setContentView(R.layout.animation_seeking); 59b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase LinearLayout container = (LinearLayout) findViewById(R.id.container); 60b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase final MyAnimationView animView = new MyAnimationView(this); 61b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase container.addView(animView); 62b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase 63b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase Button starter = (Button) findViewById(R.id.startButton); 64b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase starter.setOnClickListener(new View.OnClickListener() { 65b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase public void onClick(View v) { 66b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase animView.startAnimation(); 67b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase } 68b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase }); 69b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase 70b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase mSeekBar = (SeekBar) findViewById(R.id.seekBar); 71b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase mSeekBar.setMax(DURATION); 72b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 73b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase public void onStopTrackingTouch(SeekBar seekBar) { 74b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase } 75b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase 76b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase public void onStartTrackingTouch(SeekBar seekBar) { 77b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase } 78b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase 79b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase public void onProgressChanged(SeekBar seekBar, int progress, 80b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase boolean fromUser) { 81b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase // prevent seeking on app creation 82b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase if (animView.getHeight() != 0) { 83b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase animView.seek(progress); 84b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase } 85b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase } 86b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase }); 87b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase } 88b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase 89d9855a8dbed211de6e1c1cf55e20201349c40432Chet Haase public class MyAnimationView extends View implements ValueAnimator.AnimatorUpdateListener, Animator.AnimatorListener { 90b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase 91b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase private static final int RED = 0xffFF8080; 92b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase private static final int BLUE = 0xff8080FF; 93b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase private static final int CYAN = 0xff80ffff; 94b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase private static final int GREEN = 0xff80ff80; 95b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase private static final float BALL_SIZE = 100f; 96b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase 97b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase public final ArrayList<ShapeHolder> balls = new ArrayList<ShapeHolder>(); 98d9855a8dbed211de6e1c1cf55e20201349c40432Chet Haase AnimatorSet animation = null; 99d9855a8dbed211de6e1c1cf55e20201349c40432Chet Haase ValueAnimator bounceAnim = null; 100b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase ShapeHolder ball = null; 101b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase 102b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase public MyAnimationView(Context context) { 103b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase super(context); 104b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase ball = addBall(200, 0); 105b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase } 106b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase 107b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase private void createAnimation() { 108b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase if (bounceAnim == null) { 109e358b47be5a1c1a775a376925ea063b51ec3a3f9Chet Haase bounceAnim = ObjectAnimator.ofFloat(ball, "y", 110e358b47be5a1c1a775a376925ea063b51ec3a3f9Chet Haase ball.getY(), getHeight() - BALL_SIZE).setDuration(1500); 111b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase bounceAnim.setInterpolator(new BounceInterpolator()); 112b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase bounceAnim.addUpdateListener(this); 113b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase } 114b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase } 115b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase 116b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase public void startAnimation() { 117b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase createAnimation(); 118b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase bounceAnim.start(); 119b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase } 120b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase 121b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase public void seek(long seekTime) { 122b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase createAnimation(); 123b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase bounceAnim.setCurrentPlayTime(seekTime); 124b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase } 125b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase 126b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase private ShapeHolder addBall(float x, float y) { 127b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase OvalShape circle = new OvalShape(); 128b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase circle.resize(BALL_SIZE, BALL_SIZE); 129b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase ShapeDrawable drawable = new ShapeDrawable(circle); 130b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase ShapeHolder shapeHolder = new ShapeHolder(drawable); 131b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase shapeHolder.setX(x); 132b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase shapeHolder.setY(y); 133b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase int red = (int)(100 + Math.random() * 155); 134b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase int green = (int)(100 + Math.random() * 155); 135b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase int blue = (int)(100 + Math.random() * 155); 136b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase int color = 0xff000000 | red << 16 | green << 8 | blue; 137b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase Paint paint = drawable.getPaint(); 138b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase int darkColor = 0xff000000 | red/4 << 16 | green/4 << 8 | blue/4; 139b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase RadialGradient gradient = new RadialGradient(37.5f, 12.5f, 140b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase 50f, color, darkColor, Shader.TileMode.CLAMP); 141b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase paint.setShader(gradient); 142b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase shapeHolder.setPaint(paint); 143b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase balls.add(shapeHolder); 144b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase return shapeHolder; 145b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase } 146b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase 147b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase @Override 148b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase protected void onDraw(Canvas canvas) { 149b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase canvas.translate(ball.getX(), ball.getY()); 150b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase ball.getShape().draw(canvas); 151b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase } 152b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase 153d9855a8dbed211de6e1c1cf55e20201349c40432Chet Haase public void onAnimationUpdate(ValueAnimator animation) { 154b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase invalidate(); 155b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase long playtime = bounceAnim.getCurrentPlayTime(); 156b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase //mSeekBar.setProgress((int)playtime); 157b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase } 158b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase 159d9855a8dbed211de6e1c1cf55e20201349c40432Chet Haase public void onAnimationCancel(Animator animation) { 160b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase } 161b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase 162d9855a8dbed211de6e1c1cf55e20201349c40432Chet Haase public void onAnimationEnd(Animator animation) { 163d9855a8dbed211de6e1c1cf55e20201349c40432Chet Haase balls.remove(((ObjectAnimator)animation).getTarget()); 164b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase 165b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase } 166b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase 167d9855a8dbed211de6e1c1cf55e20201349c40432Chet Haase public void onAnimationRepeat(Animator animation) { 168b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase } 169b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase 170d9855a8dbed211de6e1c1cf55e20201349c40432Chet Haase public void onAnimationStart(Animator animation) { 171b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase } 172b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase } 173b9461fc8ef49e050b97d5305f32bc50099c78a16Chet Haase}