Android Property Animation API
This tutorial describes how to use Animations in Android. The
tutorial is
based on Eclipse 4.2, Java 1.6 and Android 4.2.
Table of Contents
Android 3.0 introduced the
Properties Animation API
which allow to change object properties over a predefined
time
interval.
The API allows to define for arbitrary object properties a start and end value and apply a time-based change to this attribute. This API can be applied on any Java object not only on
The API allows to define for arbitrary object properties a start and end value and apply a time-based change to this attribute. This API can be applied on any Java object not only on
Views.
The superclass of the animation API is the
You can also add an
Animator
class. Typically the
ObjectAnimator
class is used to modify the attributes of an object.
You can also add an
AnimatorListener
class to your
Animator
class. This listener is called in the different phases of the
animation. You can use this listener to perform actions before or
after a certain animation, e.g. add or remove a
View
from a
ViewGroup.
The
The
The target of
The following code shows an example of the usage of this method.
For performance optimization you can also let
You can also directly define a
The
Via the
ViewPropertyAnimator
class introduced in Android 3.1 provides a simpler access to typical
animations which are performed on
Views.
The
animate()
method on a
View
will return the
ViewPropertyAnimator
object. This object allows
to perform simultaneous animations. It
has a
fluent API and allows
to set
the duration of the animation.
The target of
ViewPropertyAnimator
is to provide a very simple API for typical animations.
The following code shows an example of the usage of this method.
// Using hardware layer
myView.animate().translationX(400).withLayer();
For performance optimization you can also let
ViewPropertyAnimator
use a hardware layout.
// Using hardware layer
myView.animate().translationX(400).withLayer();
You can also directly define a
Runnable
to be executed at the start and the end of the animation.
// StartAction myView.animate().translationX(100).withStartAction(new Runnable(){ public void run(){ viewer.setTranslationX(100-myView.getWidth()); // do something } }); // EndAction myView.animate().alpha(0).withStartAction(new Runnable(){ public void run(){ // Remove the view from the layout called parent parent.removeView(myView); } });
The
setInterpolator()
allows to define an object of type
TimeInterpolator
which defines the change of the value over time. The standard is
linear. The Android platform
defines a few default ones as for example
AccelerateDecelerateInterpolator
where the rate of change starts and ends slowly but accelerates
through the middle.
Via the
setEvaluator
method you can set an object of type
TypeEvaluator
which allow you to create animations on arbitrary property
types, by
providing custom evaluators for types that
are not automatically
understood and used by the animation system.
The
LayoutTransition
class allows to set animations on a layout container and a changes on
the
Views
of this container will be animated.
package com.example.android.layoutanimation; import android.animation.LayoutTransition; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.view.ViewGroup; import android.widget.Button; public class MainActivity extends Activity { private ViewGroup viewGroup; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); LayoutTransition l = new LayoutTransition(); l.enableTransitionType(LayoutTransition.CHANGING); viewGroup = (ViewGroup) findViewById(R.id.container); viewGroup.setLayoutTransition(l); } public void onClick(View view) { viewGroup.addView(new Button(this)); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_main, menu); return true; } }
Animations can be applied to
The
Views
but it is also possible to apply them on the transition between
activities.
The
ActivityOptions
class
allows to define default or customer animations.
public void onClick(View view) { Intent intent = new Intent(this, SecondActivity.class); ActivityOptions options = ActivityOptions.makeScaleUpAnimation(view, 0, 0, view.getWidth(), view.getHeight()); startActivity(intent, options.toBundle()); }
The following description assumes that you have already basic
knowledge in Android development.
Please check the Android development tutorial to learn the basics. Also see Android development tutorials for more information about Android development.
Please check the Android development tutorial to learn the basics. Also see Android development tutorials for more information about Android development.
This tutorial demonstrates the usage of the
Properties Animation
API.
Create a new Android project called com.vogella.android.animation.views with the activity called AnimationExampleActivity. The layout file should be called
Create the following menu resource.
Change your activity to the following.
Create a new activity called HitActivity.
If you run this example and press the different Buttons, the animation should start. Via the ActionBar you can navigate to your other activity.
Create a new Android project called com.vogella.android.animation.views with the activity called AnimationExampleActivity. The layout file should be called
main.xml. Change this file
to the
following code.
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/layout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <LinearLayout android:id="@+id/test" android:layout_width="wrap_content" android:layout_height="wrap_content" > <Button android:id="@+id/Button01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="startAnimation" android:text="Rotate" /> <Button android:id="@+id/Button04" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="startAnimation" android:text="Group" > </Button> <Button android:id="@+id/Button03" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="startAnimation" android:text="Fade" /> <Button android:id="@+id/Button02" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="startAnimation" android:text="Animate" /> </LinearLayout> <ImageView android:id="@+id/imageView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:src="@drawable/icon" /> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/imageView1" android:layout_alignRight="@+id/imageView1" android:layout_marginBottom="30dp" android:text="Large Text" android:textAppearance="?android:attr/textAppearanceLarge" /> </RelativeLayout>
Create the following menu resource.
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/item1" android:showAsAction="ifRoom" android:title="Game"> </item> </menu>
Change your activity to the following.
package com.vogella.android.animation.views; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.app.Activity; import android.content.Intent; import android.graphics.Paint; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.ImageView; import android.widget.TextView; public class AnimationExampleActivity extends Activity {/** Called when the activity is first created. */@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } public void startAnimation(View view) { float dest = 0; ImageView aniView = (ImageView) findViewById(R.id.imageView1); switch (view.getId()) { case R.id.Button01: dest = 360; if (aniView.getRotation() == 360) { System.out.println(aniView.getAlpha()); dest = 0; } ObjectAnimator animation1 = ObjectAnimator.ofFloat(aniView, "rotation", dest); animation1.setDuration(2000); animation1.start(); // Show how to load an animation from XML // Animation animation1 = AnimationUtils.loadAnimation(this, // R.anim.myanimation); // animation1.setAnimationListener(this); // animatedView1.startAnimation(animation1); break; case R.id.Button02: // shows how to define a animation via code // also use an Interpolator (BounceInterpolator) Paint paint = new Paint(); TextView aniTextView = (TextView) findViewById(R.id.textView1); float measureTextCenter = paint.measureText(aniTextView.getText() .toString()); dest = 0 - measureTextCenter; if (aniTextView.getX() < 0) { dest = 0; } ObjectAnimator animation2 = ObjectAnimator.ofFloat(aniTextView, "x", dest); animation2.setDuration(2000); animation2.start(); break; case R.id.Button03: // demonstrate fading and adding an AnimationListener dest = 1; if (aniView.getAlpha() > 0) { dest = 0; } ObjectAnimator animation3 = ObjectAnimator.ofFloat(aniView, "alpha", dest); animation3.setDuration(2000); animation3.start(); break; case R.id.Button04: ObjectAnimator fadeOut = ObjectAnimator.ofFloat(aniView, "alpha", 0f); fadeOut.setDuration(2000); ObjectAnimator mover = ObjectAnimator.ofFloat(aniView, "translationX", -500f, 0f); mover.setDuration(2000); ObjectAnimator fadeIn = ObjectAnimator.ofFloat(aniView, "alpha", 0f, 1f); fadeIn.setDuration(2000); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(mover).with(fadeIn).after(fadeOut); animatorSet.start(); break; default: break; } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.mymenu, menu); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { Intent intent = new Intent(this, HitActivity.class); startActivity(intent); return true; } }
Create a new activity called HitActivity.
package com.vogella.android.animation.views; import java.util.Random; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.Button; public class HitActivity extends Activity { private ObjectAnimator animation1; private ObjectAnimator animation2; private Button button; private Random randon; private int width; private int height; private AnimatorSet set; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.target); width = getWindowManager().getDefaultDisplay().getWidth(); height = getWindowManager().getDefaultDisplay().getHeight(); randon = new Random(); set = createAnimation(); set.start(); set.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { int nextX = randon.nextInt(width); int nextY = randon.nextInt(height); animation1 = ObjectAnimator.ofFloat(button, "x", button.getX(), nextX); animation1.setDuration(1400); animation2 = ObjectAnimator.ofFloat(button, "y", button.getY(), nextY); animation2.setDuration(1400); set.playTogether(animation1, animation2); set.start(); } }); } public void onClick(View view) { String string = button.getText().toString(); int hitTarget = Integer.valueOf(string) + 1; button.setText(String.valueOf(hitTarget)); } private AnimatorSet createAnimation() { int nextX = randon.nextInt(width); int nextY = randon.nextInt(height); button = (Button) findViewById(R.id.button1); animation1 = ObjectAnimator.ofFloat(button, "x", nextX); animation1.setDuration(1400); animation2 = ObjectAnimator.ofFloat(button, "y", nextY); animation2.setDuration(1400); AnimatorSet set = new AnimatorSet(); set.playTogether(animation1, animation2); return set; } }
If you run this example and press the different Buttons, the animation should start. Via the ActionBar you can navigate to your other activity.
During a fragment transaction you can define animations which
should be
used based on the Property Animation API via the
You can also use several standard animations provided by Android via the
Both methods allow you to define an entry animation and an existing animation.
setCustomAnimations()
method.
You can also use several standard animations provided by Android via the
setTransition()
method call.
These are defined via the constants starting with
FragmentTransaction.TRANSIT_FRAGMENT_*.
Both methods allow you to define an entry animation and an existing animation.
Jake Wharton created a library which allow to use the Properties
Animation API also in Android releases before Android 4.0.
You find more information on the project website: NineOldAndroids
You find more information on the project website: NineOldAndroids
No comments:
Post a Comment