docs: animations au class
Change-Id: I776ccdf44014fe38dd55dedfed8730306d2a2cea
diff --git a/docs/downloads/training/Animations.zip b/docs/downloads/training/Animations.zip
new file mode 100644
index 0000000..5063dd1
--- /dev/null
+++ b/docs/downloads/training/Animations.zip
Binary files differ
diff --git a/docs/html/training/animation/anim_card_flip.mp4 b/docs/html/training/animation/anim_card_flip.mp4
new file mode 100755
index 0000000..e885f98
--- /dev/null
+++ b/docs/html/training/animation/anim_card_flip.mp4
Binary files differ
diff --git a/docs/html/training/animation/anim_card_flip.ogv b/docs/html/training/animation/anim_card_flip.ogv
new file mode 100755
index 0000000..33cd86c
--- /dev/null
+++ b/docs/html/training/animation/anim_card_flip.ogv
Binary files differ
diff --git a/docs/html/training/animation/anim_card_flip.webm b/docs/html/training/animation/anim_card_flip.webm
new file mode 100755
index 0000000..a670d78
--- /dev/null
+++ b/docs/html/training/animation/anim_card_flip.webm
Binary files differ
diff --git a/docs/html/training/animation/anim_crossfade.mp4 b/docs/html/training/animation/anim_crossfade.mp4
new file mode 100644
index 0000000..ced7cc9
--- /dev/null
+++ b/docs/html/training/animation/anim_crossfade.mp4
Binary files differ
diff --git a/docs/html/training/animation/anim_crossfade.ogv b/docs/html/training/animation/anim_crossfade.ogv
new file mode 100644
index 0000000..7ec417a
--- /dev/null
+++ b/docs/html/training/animation/anim_crossfade.ogv
Binary files differ
diff --git a/docs/html/training/animation/anim_crossfade.webm b/docs/html/training/animation/anim_crossfade.webm
new file mode 100644
index 0000000..21e7228
--- /dev/null
+++ b/docs/html/training/animation/anim_crossfade.webm
Binary files differ
diff --git a/docs/html/training/animation/anim_layout_changes.mp4 b/docs/html/training/animation/anim_layout_changes.mp4
new file mode 100644
index 0000000..0709601
--- /dev/null
+++ b/docs/html/training/animation/anim_layout_changes.mp4
Binary files differ
diff --git a/docs/html/training/animation/anim_layout_changes.ogv b/docs/html/training/animation/anim_layout_changes.ogv
new file mode 100644
index 0000000..75f5250
--- /dev/null
+++ b/docs/html/training/animation/anim_layout_changes.ogv
Binary files differ
diff --git a/docs/html/training/animation/anim_layout_changes.webm b/docs/html/training/animation/anim_layout_changes.webm
new file mode 100644
index 0000000..a99a566
--- /dev/null
+++ b/docs/html/training/animation/anim_layout_changes.webm
Binary files differ
diff --git a/docs/html/training/animation/anim_screenslide.mp4 b/docs/html/training/animation/anim_screenslide.mp4
new file mode 100755
index 0000000..3e65026
--- /dev/null
+++ b/docs/html/training/animation/anim_screenslide.mp4
Binary files differ
diff --git a/docs/html/training/animation/anim_screenslide.ogv b/docs/html/training/animation/anim_screenslide.ogv
new file mode 100755
index 0000000..c45ebd4
--- /dev/null
+++ b/docs/html/training/animation/anim_screenslide.ogv
Binary files differ
diff --git a/docs/html/training/animation/anim_screenslide.webm b/docs/html/training/animation/anim_screenslide.webm
new file mode 100755
index 0000000..c72adbc
--- /dev/null
+++ b/docs/html/training/animation/anim_screenslide.webm
Binary files differ
diff --git a/docs/html/training/animation/anim_zoom.mp4 b/docs/html/training/animation/anim_zoom.mp4
new file mode 100644
index 0000000..4326c35
--- /dev/null
+++ b/docs/html/training/animation/anim_zoom.mp4
Binary files differ
diff --git a/docs/html/training/animation/anim_zoom.ogv b/docs/html/training/animation/anim_zoom.ogv
new file mode 100644
index 0000000..e5793f3
--- /dev/null
+++ b/docs/html/training/animation/anim_zoom.ogv
Binary files differ
diff --git a/docs/html/training/animation/anim_zoom.webm b/docs/html/training/animation/anim_zoom.webm
new file mode 100644
index 0000000..b3b7566
--- /dev/null
+++ b/docs/html/training/animation/anim_zoom.webm
Binary files differ
diff --git a/docs/html/training/animation/cardflip.jd b/docs/html/training/animation/cardflip.jd
new file mode 100644
index 0000000..ab3eb3a
--- /dev/null
+++ b/docs/html/training/animation/cardflip.jd
@@ -0,0 +1,365 @@
+page.title=Displaying Card Flip Animations
+trainingnavtop=true
+
+@jd:body
+ <div id="tb-wrapper">
+ <div id="tb">
+ <h2>
+ This lesson teaches you to
+ </h2>
+ <ol>
+ <li>
+ <a href="#animators">Create the Animators</a>
+ </li>
+ <li>
+ <a href="#views">Create the Views</a>
+ </li>
+ <li>
+ <a href="#fragment">Create the Fragment</a>
+ </li>
+ <li>
+ <a href="#animate">Animate the Card Flip</a>
+ </li>
+ </ol>
+ </div>
+ </div>
+ <p> This lesson shows you how to do a card flip
+ animation with custom fragment animations.
+ Card flips animate between views of content by showing an animation that emulates
+ a card flipping over.
+ </p>
+ <p>Here's what a card flip looks like:
+ </p>
+
+ <div class="framed-galaxynexus-land-span-8">
+ <video class="play-on-hover" autoplay>
+ <source src="anim_card_flip.mp4" type="video/mp4">
+ <source src="anim_card_flip.webm" type="video/webm">
+ <source src="anim_card_flip.ogv" type="video/ogg">
+ </video>
+ </div>
+ <div class="figure-caption">
+ Card flip animation
+ <div class="video-instructions"> </div>
+ </div>
+
+ <p>
+ If you want to jump ahead and see a full working example,
+ <a href="{@docRoot}shareables/training/Animations.zip">download</a> and
+ run the sample app and select the Card Flip example. See the following
+ files for the code implementation:
+ </p>
+ <ul>
+ <li>
+ <code>src/CardFlipActivity.java</code>
+ </li>
+ <li>
+ <code>animator/card_flip_right_in.xml</code>
+ </li>
+ <li>
+ <code>animator/card_flip_right_out.xml</code>
+ </li>
+ <li>
+ <code>animator/card_flip_right_in.xml</code>
+ </li>
+ <li>
+ <code>animator/card_flip_left_out.xml</code>
+ </li>
+ <li>
+ <code>layout/fragment_card_back.xml</code>
+ </li>
+ <li>
+ <code>layout/fragment_card_front.xml</code>
+ </li>
+ </ul>
+
+ <h2 id="animate">
+ Create the Animators
+ </h2>
+ <p>
+ Create the animations for the card flips. You'll need two animators for when the front
+ of the card animates out and to the left and in and from the left. You'll also need two animators
+ for when the back of the card animates in and from the right and out and to the right.
+ </p>
+ <h4>
+ card_flip_left_in.xml
+ </h4>
+<pre>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <!-- Before rotating, immediately set the alpha to 0. -->
+ <objectAnimator
+ android:valueFrom="1.0"
+ android:valueTo="0.0"
+ android:propertyName="alpha"
+ android:duration="0" />
+
+ <!-- Rotate. -->
+ <objectAnimator
+ android:valueFrom="-180"
+ android:valueTo="0"
+ android:propertyName="rotationY"
+ android:interpolator="@android:interpolator/accelerate_decelerate"
+ android:duration="@integer/card_flip_time_full" />
+
+ <!-- Half-way through the rotation (see startOffset), set the alpha to 1. -->
+ <objectAnimator
+ android:valueFrom="0.0"
+ android:valueTo="1.0"
+ android:propertyName="alpha"
+ android:startOffset="@integer/card_flip_time_half"
+ android:duration="1" />
+</set>
+</pre>
+ <h4>
+ card_flip_left_out.xml
+ </h4>
+ <pre>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <!-- Rotate. -->
+ <objectAnimator
+ android:valueFrom="0"
+ android:valueTo="180"
+ android:propertyName="rotationY"
+ android:interpolator="@android:interpolator/accelerate_decelerate"
+ android:duration="@integer/card_flip_time_full" />
+
+ <!-- Half-way through the rotation (see startOffset), set the alpha to 0. -->
+ <objectAnimator
+ android:valueFrom="1.0"
+ android:valueTo="0.0"
+ android:propertyName="alpha"
+ android:startOffset="@integer/card_flip_time_half"
+ android:duration="1" />
+</set>
+ </pre>
+ <h4>
+ card_flip_right_in.xml
+ </h4>
+ <pre>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <!-- Before rotating, immediately set the alpha to 0. -->
+ <objectAnimator
+ android:valueFrom="1.0"
+ android:valueTo="0.0"
+ android:propertyName="alpha"
+ android:duration="0" />
+
+ <!-- Rotate. -->
+ <objectAnimator
+ android:valueFrom="180"
+ android:valueTo="0"
+ android:propertyName="rotationY"
+ android:interpolator="@android:interpolator/accelerate_decelerate"
+ android:duration="@integer/card_flip_time_full" />
+
+ <!-- Half-way through the rotation (see startOffset), set the alpha to 1. -->
+ <objectAnimator
+ android:valueFrom="0.0"
+ android:valueTo="1.0"
+ android:propertyName="alpha"
+ android:startOffset="@integer/card_flip_time_half"
+ android:duration="1" />
+</set>
+
+</pre>
+ <h4>
+ card_flip_right_out.xml
+ </h4>
+ <pre>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <!-- Rotate. -->
+ <objectAnimator
+ android:valueFrom="0"
+ android:valueTo="-180"
+ android:propertyName="rotationY"
+ android:interpolator="@android:interpolator/accelerate_decelerate"
+ android:duration="@integer/card_flip_time_full" />
+
+ <!-- Half-way through the rotation (see startOffset), set the alpha to 0. -->
+ <objectAnimator
+ android:valueFrom="1.0"
+ android:valueTo="0.0"
+ android:propertyName="alpha"
+ android:startOffset="@integer/card_flip_time_half"
+ android:duration="1" />
+</set>
+</pre>
+ <h2 id="views">
+ Create the Views
+ </h2>
+ <p>
+ Each side of the "card" is a separate layout that can contain any content you want,
+ such as two screens of text, two images, or any combination of views to flip between. You'll then
+ use the two layouts in the fragments that you'll later animate. The following layouts
+ create one side of a card that shows text:
+ </p>
+
+ <pre>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:background="#a6c"
+ android:padding="16dp"
+ android:gravity="bottom">
+
+ <TextView android:id="@android:id/text1"
+ style="?android:textAppearanceLarge"
+ android:textStyle="bold"
+ android:textColor="#fff"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/card_back_title" />
+
+ <TextView style="?android:textAppearanceSmall"
+ android:textAllCaps="true"
+ android:textColor="#80ffffff"
+ android:textStyle="bold"
+ android:lineSpacingMultiplier="1.2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/card_back_description" />
+
+</LinearLayout>
+</pre>
+<p>
+and the other side of the card that displays an {@link android.widget.ImageView}:
+</p>
+<pre>
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:src="@drawable/image1"
+ android:scaleType="centerCrop"
+ android:contentDescription="@string/description_image_1" />
+</pre>
+ <h2 id="fragment">
+ Create the Fragment
+ </h2>
+ <p>
+ Create fragment classes for the front and back of the card. These classes return the layouts
+ that you created previously in the {@link android.app.Fragment#onCreateView onCreateView()} method
+ of each fragment. You can then create instances of this fragment in the parent activity
+ where you want to show the card. The following example shows nested fragment classes inside
+ of the parent activity that uses them:
+ </p>
+ <pre>
+public class CardFlipActivity extends Activity {
+ ...
+ /**
+ * A fragment representing the front of the card.
+ */
+ public class CardFrontFragment extends Fragment {
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.fragment_card_front, container, false);
+ }
+ }
+
+ /**
+ * A fragment representing the back of the card.
+ */
+ public class CardBackFragment extends Fragment {
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.fragment_card_back, container, false);
+ }
+ }
+}
+</pre>
+ <h2 id="animate">
+ Animate the Card Flip
+ </h2>
+
+ <p> Now, you'll need to display the fragments inside of a parent activity.
+ To do this, first create the layout for your activity. The following example creates a
+ {@link android.widget.FrameLayout} that you
+ can add fragments to at runtime:</p>
+
+ <pre>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+</pre>
+
+ <p>In the activity code, set the content view to be the layout that you just created. It's also
+ good idea to show a default fragment when the activity is created, so the following example
+ activity shows you how to display the front of the card by default:
+ </p>
+
+
+
+<pre>
+public class CardFlipActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_activity_card_flip);
+
+ if (savedInstanceState == null) {
+ getFragmentManager()
+ .beginTransaction()
+ .add(R.id.container, new CardFrontFragment())
+ .commit();
+ }
+ }
+ ...
+}
+</pre>
+ <p>
+ Now that you have the front of the card showing, you can show the back of the card
+ with the flip animation at an appropriate time. Create a method to show the other
+ side of the card that does the following things:
+ </p>
+ <ul>
+ <li>Sets the custom animations that you created earlier for the fragment transitions.
+ </li>
+ <li>Replaces the currently displayed fragment with a new fragment and animates this event
+ with the custom animations that you created.
+ </li>
+ <li>Adds the previously displayed fragment to the fragment back stack
+ so when the user presses the <em>Back</em> button, the card flips back over.
+ </li>
+ </ul>
+ <pre>
+private void flipCard() {
+ if (mShowingBack) {
+ getFragmentManager().popBackStack();
+ return;
+ }
+
+ // Flip to the back.
+
+ mShowingBack = true;
+
+ // Create and commit a new fragment transaction that adds the fragment for the back of
+ // the card, uses custom animations, and is part of the fragment manager's back stack.
+
+ getFragmentManager()
+ .beginTransaction()
+
+ // Replace the default fragment animations with animator resources representing
+ // rotations when switching to the back of the card, as well as animator
+ // resources representing rotations when flipping back to the front (e.g. when
+ // the system Back button is pressed).
+ .setCustomAnimations(
+ R.animator.card_flip_right_in, R.animator.card_flip_right_out,
+ R.animator.card_flip_left_in, R.animator.card_flip_left_out)
+
+ // Replace any fragments currently in the container view with a fragment
+ // representing the next page (indicated by the just-incremented currentPage
+ // variable).
+ .replace(R.id.container, new CardBackFragment())
+
+ // Add this transaction to the back stack, allowing users to press Back
+ // to get to the front of the card.
+ .addToBackStack(null)
+
+ // Commit the transaction.
+ .commit();
+}
+</pre>
\ No newline at end of file
diff --git a/docs/html/training/animation/crossfade.jd b/docs/html/training/animation/crossfade.jd
new file mode 100644
index 0000000..99e879b
--- /dev/null
+++ b/docs/html/training/animation/crossfade.jd
@@ -0,0 +1,208 @@
+page.title=Crossfading Two Views
+trainingnavtop=true
+
+
+@jd:body
+
+ <div id="tb-wrapper">
+ <div id="tb">
+ <h2>
+ This lesson teaches you to:
+ </h2>
+ <ol>
+ <li>
+ <a href="#views">Create the Views</a>
+ </li>
+ <li>
+ <a href="#setup">Set up the Animation</a>
+ </li>
+ <li>
+ <a href="#animate">Crossfade the Views</a>
+ </li>
+ </ol>
+ </div>
+ </div>
+
+ <p>
+ Crossfade animations (also know as dissolve) gradually fade out one UI component while simultaneously fading in
+ another. This animation is useful for situations where you want to switch content or views
+ in your app. Crossfades are very subtle and short but offer a fluid transition from one screen to the
+ next. When you don't use them, however, transitions often feel abrupt or hurried.
+ </p>
+ <p>Here's an example of a crossfade from a progress indicator to some text content.
+ </p>
+
+<div class="framed-galaxynexus-land-span-8">
+ <video class="play-on-hover" autoplay>
+ <source src="anim_crossfade.mp4" type="video/mp4">
+ <source src="anim_crossfade.webm" type="video/webm">
+ <source src="anim_crossfade.ogv" type="video/ogg">
+ </video>
+</div>
+<div class="figure-caption">
+Crossfade animation
+ <div class="video-instructions"> </div>
+</div>
+
+ <p>
+ If you want to jump ahead and see a full working example,
+ <a href="{@docRoot}shareables/training/Animations.zip">download</a>
+ and run the sample app and select the Crossfade example.
+ See the following files for the code implementation:
+ </p>
+ <ul>
+ <li>
+ <code>src/CrossfadeActivity.java</code>
+ </li>
+ <li>
+ <code>layout/activity_crossfade.xml</code>
+ </li>
+ <li>
+ <code>menu/activity_crossfade.xml</code>
+ </li>
+ </ul>
+ <h2 id="views">
+ Create the Views
+ </h2>
+ <p>
+ Create the two views that you want to crossfade. The following example creates a progress
+ indicator and a scrollable text view:
+ </p>
+ <pre>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <TextView style="?android:textAppearanceMedium"
+ android:lineSpacingMultiplier="1.2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/lorem_ipsum"
+ android:padding="16dp" />
+
+ </ScrollView>
+
+ <ProgressBar android:id="@+id/loading_spinner"
+ style="?android:progressBarStyleLarge"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center" />
+
+</FrameLayout>
+</pre>
+ <h2 id="setup">
+ Set up the Animation
+ </h2>
+ <p>
+ To set up the animation:
+ </p>
+ <ol>
+ <li>Create member variables for the views that you want to crossfade. You need
+ these references later when modifying the views during the animation.
+ </li>
+ <li>For the view that is being faded in, set its visibility to {@link
+ android.view.View#GONE}. This prevents the view from taking up layout space and omits it
+ from layout calculations, speeding up processing.
+ </li>
+ <li>Cache the <code>{@link android.R.integer#config_shortAnimTime}</code>
+ system property in a member variable. This property defines a standard
+ "short" duration for the animation. This duration is ideal for subtle animations or
+ animations that occur very frequently. {@link android.R.integer#config_longAnimTime} and
+ {@link android.R.integer#config_mediumAnimTime} are also available if you wish to use them.
+ </li>
+ </ol>
+ <p>
+ Here's an example using the layout from the previous code snippet as the activity content
+ view:
+ </p>
+ <pre>
+public class CrossfadeActivity extends Activity {
+
+ private View mContentView;
+ private View mLoadingView;
+ private int mShortAnimationDuration;
+
+ ...
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_crossfade);
+
+ mContentView = findViewById(R.id.content);
+ mLoadingView = findViewById(R.id.loading_spinner);
+
+ // Initially hide the content view.
+ mContentView.setVisibility(View.GONE);
+
+ // Retrieve and cache the system's default "short" animation time.
+ mShortAnimationDuration = getResources().getInteger(
+ android.R.integer.config_shortAnimTime);
+ }
+
+</pre>
+ <h2 id="animate">
+ Crossfade the Views
+ </h2>
+ <p>
+ Now that the views are properly set up, crossfade them by doing the following:
+ </p>
+ <ol>
+ <li>For the view that is fading in, set the alpha value to <code>0</code> and the visibility
+ to {@link android.view.View#VISIBLE}. (Remember that it was initially set to {@link
+ android.view.View#GONE}.) This makes the view visible but completely transparent.
+ </li>
+ <li>For the view that is fading in, animate its alpha value from <code>0</code> to
+ <code>1</code>. At the same time, for the view that is fading out, animate the alpha value
+ from <code>1</code> to <code>0</code>.
+ </li>
+ <li>Using {@link android.animation.Animator.AnimatorListener#onAnimationEnd onAnimationEnd()}
+ in an {@link android.animation.Animator.AnimatorListener}, set the visibility of the view
+ that was fading out to {@link android.view.View#GONE}. Even though the alpha value is <code>0</code>,
+ setting the view's visibility to {@link android.view.View#GONE} prevents the view from taking
+ up layout space and omits it from layout calculations, speeding up processing.
+ </li>
+ </ol>
+ <p>
+ The following method shows an example of how to do this:
+ </p>
+ <pre>
+private View mContentView;
+private View mLoadingView;
+private int mShortAnimationDuration;
+
+...
+
+private void crossfade() {
+
+ // Set the content view to 0% opacity but visible, so that it is visible
+ // (but fully transparent) during the animation.
+ mContentView.setAlpha(0f);
+ mContentView.setVisibility(View.VISIBLE);
+
+ // Animate the content view to 100% opacity, and clear any animation
+ // listener set on the view.
+ mContentView.animate()
+ .alpha(1f)
+ .setDuration(mShortAnimationDuration)
+ .setListener(null);
+
+ // Animate the loading view to 0% opacity. After the animation ends,
+ // set its visibility to GONE as an optimization step (it won't
+ // participate in layout passes, etc.)
+ mHideView.animate()
+ .alpha(0f)
+ .setDuration(mShortAnimationDuration)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mHideView.setVisibility(View.GONE);
+ }
+ });
+}
+</pre>
\ No newline at end of file
diff --git a/docs/html/training/animation/index.jd b/docs/html/training/animation/index.jd
new file mode 100644
index 0000000..9cc7e6c
--- /dev/null
+++ b/docs/html/training/animation/index.jd
@@ -0,0 +1,86 @@
+page.title=Adding Animations
+trainingnavtop=true
+startpage=true
+
+@jd:body
+ <div id="tb-wrapper">
+ <div id="tb">
+ <h2>
+ Dependencies and prerequisites
+ </h2>
+ <ul>
+ <li>Android 4.0 or later
+ </li>
+ <li>Experience building an Android <a href="{@docRoot}guide/topics/ui/index.html">User
+ Interface</a>
+ </li>
+ </ul>
+ <h2>
+ You should also read
+ </h2>
+ <ul>
+ <li>
+ <a href="{@docRoot}guide/topics/graphics/prop-animation.html">Property Animation</a>
+ </li>
+ </ul>
+ <h2>
+ Try it out
+ </h2>
+ <div class="download-box">
+ <a href="{@docRoot}shareables/training/Animations.zip" class=
+ "button">Download the sample app</a>
+ <p class="filename">
+ Animations.zip
+ </p>
+ </div>
+ </div>
+ </div>
+ <p>
+ Animations can add subtle visual cues that notify users about what's going on in your app and
+ improve their mental model of your app's interface. Animations are especially useful when the
+ screen changes state, such as when content loads or new actions become available. Animations
+ can also add a polished look to your app, which gives your app a higher quality feel.
+ </p>
+ <p>
+ Keep in mind though, that overusing animations or using them at the wrong time can be
+ detrimental, such as when they cause delays. This training class shows you how to
+ implement some common types of animations that can increase usability and add flair without
+ annoying your users.
+ </p>
+
+ <h2>
+ Lessons
+ </h2>
+ <dl>
+ <dt>
+ <b><a href="crossfade.html">Crossfading Two Views</a></b>
+ </dt>
+ <dd>
+ Learn how to crossfade between two overlapping views. This lesson shows you how to crossfade a progress
+ indicator to a view that contains text content.
+ </dd>
+ <dt>
+ <b><a href="screen-slide.html">Using ViewPager for Screen Slides</a></b>
+ </dt>
+ <dd>
+ Learn how to animate between horizontally adjacent screens with a sliding transition.
+ </dd>
+ <dt>
+ <b><a href="cardflip.html">Displaying Card Flip Animations</a></b>
+ </dt>
+ <dd>
+ Learn how to animate between two views with a flipping motion.
+ </dd>
+ <dt>
+ <b><a href="zoom.html">Zooming a View</a></b>
+ </dt>
+ <dd>
+ Learn how to enlarge views with a touch-to-zoom animation.
+ </dd>
+ <dt>
+ <b><a href="layout.html">Animating Layout Changes</a></b>
+ </dt>
+ <dd>
+ Learn how to enable built-in animations when adding, removing, or updating child views in a layout.
+ </dd>
+ </dl>
\ No newline at end of file
diff --git a/docs/html/training/animation/layout.jd b/docs/html/training/animation/layout.jd
new file mode 100644
index 0000000..b8e0077
--- /dev/null
+++ b/docs/html/training/animation/layout.jd
@@ -0,0 +1,77 @@
+page.title=Animating Layout Changes
+trainingnavtop=true
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to:</h2>
+ <ol>
+ <li><a href="#views">Create the Layout</a></li>
+ <li><a href="#add">Add, Update, or Remove Items from the Layout</a></li>
+ </ol>
+
+</div>
+</div>
+
+ <p>A layout animation is a pre-loaded animation that the system runs each time you make a change
+ to the layout configuration. All you need to do is set an attribute in the layout to tell the
+ Android system to animate these layout changes, and system-default animations are carried out for you.
+ </p>
+<p class="note"><strong>Tip</strong>: If you want to supply custom layout animations,
+create a {@link android.animation.LayoutTransition} object and supply it to
+the layout with the {@link android.view.ViewGroup#setLayoutTransition setLayoutTransition()}
+method.
+</p>
+ Here's what a default layout animation looks like when adding items to a list:
+</p>
+
+ <div class="framed-galaxynexus-land-span-8">
+ <video class="play-on-hover" autoplay>
+ <source src="anim_layout_changes.mp4" type="video/mp4">
+ <source src="anim_layout_changes.webm" type="video/webm">
+ <source src="anim_layout_changes.ogv" type="video/ogg">
+ </video>
+ </div>
+ <div class="figure-caption">
+ Layout animation
+ <div class="video-instructions"> </div>
+ </div>
+
+<p>If you want to jump ahead and see a full working example,
+<a href="{@docRoot}shareables/training/Animations.zip">download</a> and
+run the sample app and select the Crossfade example. See the following files for the
+code implementation:</p>
+<ol>
+ <li><code>src/LayoutChangesActivity.java</code></li>
+ <li><code>layout/activity_layout_changes.xml</code></li>
+ <li><code>menu/activity_layout_changes.xml</code></li>
+</ol>
+
+<h2 id="views">Create the Layout</h2>
+<p>In your activity's layout XML file, set the <code>android:animateLayoutChanges</code>
+ attribute to <code>true</code> for the layout that you want to enable animations for.
+ For instance:</p>
+
+<pre>
+<LinearLayout android:id="@+id/container"
+ android:animateLayoutChanges="true"
+ ...
+/>
+</pre>
+
+<h2 id="activity">Add, Update, or Remove Items from the Layout</h2>
+<p>
+Now, all you need to do is add, remove, or update items in the layout
+and the items are animated automatically:
+</p>
+<pre>
+private ViewGroup mContainerView;
+...
+private void addItem() {
+ View newView;
+ ...
+ mContainerView.addView(newView, 0);
+}
+</pre>
diff --git a/docs/html/training/animation/screen-slide.jd b/docs/html/training/animation/screen-slide.jd
new file mode 100755
index 0000000..8a7af67
--- /dev/null
+++ b/docs/html/training/animation/screen-slide.jd
@@ -0,0 +1,185 @@
+page.title=Using ViewPager for Screen Slides
+trainingnavtop=true
+
+@jd:body
+
+ <div id="tb-wrapper">
+ <div id="tb">
+ <h2>This lesson teaches you to</h2>
+ <ol>
+ <li><a href="#views">Create the Views</a></li>
+ <li><a href="#fragment">Create the Fragment</a></li>
+ <li><a href="#viewpager">Animate the Screen Slide</a></li>
+ </ol>
+ </div>
+ </div>
+ <p>
+ Screen slides are transitions between one entire screen to another and are common with UIs
+ like setup wizards or slideshows. This lesson shows you how to do screen slides with
+ a {@link android.support.v4.view.ViewPager} provided by the <a href=
+ "{@docRoot}/tools/extras/support-library.html">support library</a>.
+ {@link android.support.v4.view.ViewPager}s can animate screen slides
+ automatically. Here's what a screen slide looks like that transitions from
+ one screen of content to the next:
+ </p>
+
+ <div class="framed-galaxynexus-land-span-8">
+ <video class="play-on-hover" autoplay>
+ <source src="anim_screenslide.mp4" type="video/mp4">
+ <source src="anim_screenslide.webm" type="video/webm">
+ <source src="anim_screenslide.ogv" type="video/ogg">
+ </video>
+ </div>
+
+ <div class="figure-caption">
+ Screen slide animation
+ <div class="video-instructions"> </div>
+ </div>
+
+<p>If you want to jump ahead and see a full working example,
+<a href="{@docRoot}shareables/training/Animations.zip">download</a>
+and run the sample app and select the Screen Slide example. See the
+following files for the code implementation:</p>
+<ul>
+ <li><code>src/ScreenSlidePageFragment.java</code></li>
+ <li><code>src/ScreenSlideActivity.java</code></li>
+ <li><code>layout/activity_screen_slide.xml</code></li>
+ <li><code>layout/fragment_screen_slide_page.xml</code></li>
+</ul>
+
+<h2 id="views">Create the Views</h2>
+ <p>Create a layout file that you'll later use for the content of a fragment. The following example
+ contains a text view to display some text:
+
+<pre>
+<com.example.android.animationsdemo.ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <TextView style="?android:textAppearanceMedium"
+ android:padding="16dp"
+ android:lineSpacingMultiplier="1.2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/lorem_ipsum" />
+
+</com.example.android.animationsdemo.ScrollView>
+</pre>
+
+<h2 id="fragment">Create the Fragment</h2>
+<p>Create a {@link android.support.v4.app.Fragment} class that returns the layout
+that you just created in the {@link android.app.Fragment#onCreateView onCreateView()}
+ method. You can then create instances of this fragment in the parent activity whenever you need a new page to
+ display to the user:</p>
+
+
+<pre>
+public class ScreenSlidePageFragment extends Fragment {
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ ViewGroup rootView = (ViewGroup) inflater.inflate(
+ R.layout.fragment_screen_slide_page, container, false);
+
+ return rootView;
+ }
+}
+</pre>
+
+<h2 id="viewpager">Screen Slides with ViewPager</h2>
+
+<p>{@link android.support.v4.view.ViewPager}s have built-in swipe gestures to transition
+ through pages, and they display screen slide animations by default, so you don't need to create any. {@link android.support.v4.view.ViewPager}s use
+{@link android.support.v4.view.PagerAdapter}s as a supply for new pages to display, so the {@link android.support.v4.view.PagerAdapter} will use the
+fragment class that you created earlier.
+ </p>
+
+<p>To begin, create a layout that contains a {@link android.support.v4.view.ViewPager}:</p>
+
+<pre>
+<android.support.v4.view.ViewPager
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/pager"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+</pre>
+
+<p>Create an activity that does the following things:
+</p>
+
+<ul>
+ <li>Sets the content view to be the layout with the {@link android.support.v4.view.ViewPager}.</li>
+ <li>Create a class that extends the {@link android.support.v13.app.FragmentStatePagerAdapter} abstract class. Implement
+ the {@link android.support.v4.app.FragmentStatePagerAdapter#getItem getItem()} method to supply
+ instances of <code>ScreenSlidePageFragment</code> as new pages. The pager adapter also requires that you implement the
+ {@link android.support.v4.view.PagerAdapter#getCount getCount()} method, which returns the amount of pages the adapter will create (five in the example).
+ <li>Hooks up the {@link android.support.v4.view.PagerAdapter} to the {@link android.support.v4.view.ViewPager}</code>.</li>
+ <li>Handle's the device's back button by moving backwards in the virtual stack of fragments.
+ If the user is already on the first page, go back on the activity back stack.</li>
+</ul>
+
+<pre>
+public class ScreenSlidePagerActivity extends FragmentActivity {
+ /**
+ * The number of pages (wizard steps) to show in this demo.
+ */
+ private static final int NUM_PAGES = 5;
+
+ /**
+ * The pager widget, which handles animation and allows swiping horizontally to access previous
+ * and next wizard steps.
+ */
+ private ViewPager mPager;
+
+ /**
+ * The pager adapter, which provides the pages to the view pager widget.
+ */
+ private PagerAdapter mPagerAdapter;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_screen_slide_pager);
+
+ // Instantiate a ViewPager and a PagerAdapter.
+ mPager = (ViewPager) findViewById(R.id.pager);
+ mPagerAdapter = new ScreenSlidePagerAdapter(getFragmentManager());
+ mPager.setAdapter(mPagerAdapter);
+ }
+
+ @Override
+ public void onBackPressed() {
+ if (mPager.getCurrentItem() == 0) {
+ // If the user is currently looking at the first step, allow the system to handle the
+ // Back button. This calls finish() on this activity and pops the back stack.
+ super.onBackPressed();
+ } else {
+ // Otherwise, select the previous step.
+ mPager.setCurrentItem(mPager.getCurrentItem() - 1);
+ }
+ }
+
+ /**
+ * A simple pager adapter that represents 5 ScreenSlidePageFragment objects, in
+ * sequence.
+ */
+ private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
+ public ScreenSlidePagerAdapter(FragmentManager fm) {
+ super(fm);
+ }
+
+ @Override
+ public Fragment getItem(int position) {
+ return new ScreenSlidePageFragment();
+ }
+
+ @Override
+ public int getCount() {
+ return NUM_PAGES;
+ }
+ }
+}
+</pre>
\ No newline at end of file
diff --git a/docs/html/training/animation/zoom.jd b/docs/html/training/animation/zoom.jd
new file mode 100644
index 0000000..5dc2b6c
--- /dev/null
+++ b/docs/html/training/animation/zoom.jd
@@ -0,0 +1,320 @@
+page.title=Zooming a View
+trainingnavtop=true
+
+@jd:body
+
+ <div id="tb-wrapper">
+ <div id="tb">
+ <h2>
+ This lesson teaches you to:
+ </h2>
+ <ol>
+ <li>
+ <a href="#views">Create the Views</a>
+ </li>
+ <li>
+ <a href="#setup">Set up the Zoom Animation</a>
+ </li>
+ <li>
+ <a href="#animate">Zoom the View</a>
+ </li>
+ </ol>
+ </div>
+ </div>
+ <p>
+ This lesson demonstrates how to do a touch-to-zoom animation, which is useful for apps such as photo
+ galleries to animate a view from a thumbnail to a full-size image that fills the screen.
+ </p>
+ <p>Here's what a touch-to-zoom animation looks like that
+ expands an image thumbnail to fill the screen:
+ </p>
+
+ <div class="framed-galaxynexus-land-span-8">
+ <video class="play-on-hover" autoplay>
+ <source src="anim_zoom.mp4" type="video/mp4">
+ <source src="anim_zoom.webm" type="video/webm">
+ <source src="anim_zoom.ogv" type="video/ogg">
+ </video>
+ </div>
+ <div class="figure-caption">
+ Zoom animation
+ <div class="video-instructions"> </div>
+ </div>
+
+ <p>
+ If you want to jump ahead and see a full working example,
+ <a href="{@docRoot}shareables/training/Animations.zip">download</a> and
+ run the sample app and select the
+ Zoom example. See the following files for the code implementation:
+ </p>
+ <ul>
+ <li>
+ <code>src/TouchHighlightImageButton.java</code> (a simple helper class that shows a blue
+ touch highlight when the image button is pressed)
+ </li>
+ <li>
+ <code>src/ZoomActivity.java</code>
+ </li>
+ <li>
+ <code>layout/activity_zoom.xml</code>
+ </li>
+ </ul>
+ <h2 id="views">
+ Create the Views
+ </h2>
+ <p>
+ Create a layout file that contains the small and large version of the content that you want
+ to zoom. The following example creates an {@link android.widget.ImageButton} for clickable image thumbnail
+ and an {@link android.widget.ImageView} that displays the enlarged view of the image:
+ </p>
+ <pre>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:padding="16dp">
+
+ <ImageButton
+ android:id="@+id/thumb_button_1"
+ android:layout_width="100dp"
+ android:layout_height="75dp"
+ android:layout_marginRight="1dp"
+ android:src="@drawable/thumb1"
+ android:scaleType="centerCrop"
+ android:contentDescription="@string/description_image_1" />
+
+ </LinearLayout>
+
+ <!-- This initially-hidden ImageView will hold the expanded/zoomed version of
+ the images above. Without transformations applied, it takes up the entire
+ screen. To achieve the "zoom" animation, this view's bounds are animated
+ from the bounds of the thumbnail button above, to its final laid-out
+ bounds.
+ -->
+
+ <ImageView
+ android:id="@+id/expanded_image"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="invisible"
+ android:contentDescription="@string/description_zoom_touch_close" />
+
+</FrameLayout>
+</pre>
+ <h2 id="setup">
+ Set up the Zoom Animation
+ </h2>
+ <p>
+ Once you apply your layout, set up the event handlers that trigger the zoom animation.
+ The following example adds a {@link android.view.View.OnClickListener} to the {@link
+ android.widget.ImageButton} to execute the zoom animation when the user
+ clicks the image button:
+ </p>
+ <pre>
+public class ZoomActivity extends FragmentActivity {
+ // Hold a reference to the current animator,
+ // so that it can be canceled mid-way.
+ private Animator mCurrentAnimator;
+
+ // The system "short" animation time duration, in milliseconds. This
+ // duration is ideal for subtle animations or animations that occur
+ // very frequently.
+ private int mShortAnimationDuration;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_zoom);
+
+ // Hook up clicks on the thumbnail views.
+
+ final View thumb1View = findViewById(R.id.thumb_button_1);
+ thumb1View.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ zoomImageFromThumb(thumb1View, R.drawable.image1);
+ }
+ });
+
+ // Retrieve and cache the system's default "short" animation time.
+ mShortAnimationDuration = getResources().getInteger(
+ android.R.integer.config_shortAnimTime);
+ }
+ ...
+}
+</pre>
+ <h2 id="animate">
+ Zoom the View
+ </h2>
+ <p>
+ You'll now need to animate from the normal sized view to the zoomed view
+ when appropriate. In general, you need to animate from the bounds of the normal-sized view to the
+ bounds of the larger-sized view. The following method shows you how to implement a zoom animation that
+ zooms from an image thumbnail to an enlarged view by doing the following things:
+ </p>
+ <ol>
+ <li>Assign the high-res image to the hidden "zoomed-in" (enlarged) {@link
+ android.widget.ImageView}. The following example loads a large image resource on the UI
+ thread for simplicity. You will want to do this loading in a separate thread to prevent
+ blocking on the UI thread and then set the bitmap on the UI thread. Ideally, the bitmap
+ should not be larger than the screen size.
+ </li>
+ <li>Calculate the starting and ending bounds for the {@link android.widget.ImageView}.
+ </li>
+ <li>Animate each of the four positioning and sizing properties <code>{@link
+ android.view.View#X}</code>, <code>{@link android.view.View#Y}</code>, ({@link
+ android.view.View#SCALE_X}, and <code>{@link android.view.View#SCALE_Y}</code>)
+ simultaneously, from the starting bounds to the ending bounds. These four animations are
+ added to an {@link android.animation.AnimatorSet} so that they can be started at the same
+ time.
+ </li>
+ <li>Zoom back out by running a similar animation but in reverse when the user touches the
+ screen when the image is zoomed in. You can do this by adding a {@link
+ android.view.View.OnClickListener} to the {@link android.widget.ImageView}. When clicked, the
+ {@link android.widget.ImageView} minimizes back down to the size of the image thumbnail and
+ sets its visibility to {@link android.view.View#GONE} to hide it.
+ </li>
+ </ol>
+ <pre>
+private void zoomImageFromThumb(final View thumbView, int imageResId) {
+ // If there's an animation in progress, cancel it
+ // immediately and proceed with this one.
+ if (mCurrentAnimator != null) {
+ mCurrentAnimator.cancel();
+ }
+
+ // Load the high-resolution "zoomed-in" image.
+ final ImageView expandedImageView = (ImageView) findViewById(
+ R.id.expanded_image);
+ expandedImageView.setImageResource(imageResId);
+
+ // Calculate the starting and ending bounds for the zoomed-in image.
+ // This step involves lots of math. Yay, math.
+ final Rect startBounds = new Rect();
+ final Rect finalBounds = new Rect();
+ final Point globalOffset = new Point();
+
+ // The start bounds are the global visible rectangle of the thumbnail,
+ // and the final bounds are the global visible rectangle of the container
+ // view. Also set the container view's offset as the origin for the
+ // bounds, since that's the origin for the positioning animation
+ // properties (X, Y).
+ thumbView.getGlobalVisibleRect(startBounds);
+ findViewById(R.id.container)
+ .getGlobalVisibleRect(finalBounds, globalOffset);
+ startBounds.offset(-globalOffset.x, -globalOffset.y);
+ finalBounds.offset(-globalOffset.x, -globalOffset.y);
+
+ // Adjust the start bounds to be the same aspect ratio as the final
+ // bounds using the "center crop" technique. This prevents undesirable
+ // stretching during the animation. Also calculate the start scaling
+ // factor (the end scaling factor is always 1.0).
+ float startScale;
+ if ((float) finalBounds.width() / finalBounds.height()
+ > (float) startBounds.width() / startBounds.height()) {
+ // Extend start bounds horizontally
+ startScale = (float) startBounds.height() / finalBounds.height();
+ float startWidth = startScale * finalBounds.width();
+ float deltaWidth = (startWidth - startBounds.width()) / 2;
+ startBounds.left -= deltaWidth;
+ startBounds.right += deltaWidth;
+ } else {
+ // Extend start bounds vertically
+ startScale = (float) startBounds.width() / finalBounds.width();
+ float startHeight = startScale * finalBounds.height();
+ float deltaHeight = (startHeight - startBounds.height()) / 2;
+ startBounds.top -= deltaHeight;
+ startBounds.bottom += deltaHeight;
+ }
+
+ // Hide the thumbnail and show the zoomed-in view. When the animation
+ // begins, it will position the zoomed-in view in the place of the
+ // thumbnail.
+ thumbView.setAlpha(0f);
+ expandedImageView.setVisibility(View.VISIBLE);
+
+ // Set the pivot point for SCALE_X and SCALE_Y transformations
+ // to the top-left corner of the zoomed-in view (the default
+ // is the center of the view).
+ expandedImageView.setPivotX(0f);
+ expandedImageView.setPivotY(0f);
+
+ // Construct and run the parallel animation of the four translation and
+ // scale properties (X, Y, SCALE_X, and SCALE_Y).
+ AnimatorSet set = new AnimatorSet();
+ set
+ .play(ObjectAnimator.ofFloat(expandedImageView, View.X,
+ startBounds.left, finalBounds.left))
+ .with(ObjectAnimator.ofFloat(expandedImageView, View.Y,
+ startBounds.top, finalBounds.top))
+ .with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_X,
+ startScale, 1f)).with(ObjectAnimator.ofFloat(expandedImageView,
+ View.SCALE_Y, startScale, 1f));
+ set.setDuration(mShortAnimationDuration);
+ set.setInterpolator(new DecelerateInterpolator());
+ set.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mCurrentAnimator = null;
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mCurrentAnimator = null;
+ }
+ });
+ set.start();
+ mCurrentAnimator = set;
+
+ // Upon clicking the zoomed-in image, it should zoom back down
+ // to the original bounds and show the thumbnail instead of
+ // the expanded image.
+ final float startScaleFinal = startScale;
+ expandedImageView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (mCurrentAnimator != null) {
+ mCurrentAnimator.cancel();
+ }
+
+ // Animate the four positioning/sizing properties in parallel,
+ // back to their original values.
+ AnimatorSet set = new AnimatorSet();
+ set.play(ObjectAnimator
+ .ofFloat(expandedImageView, View.X, startBounds.left))
+ .with(ObjectAnimator
+ .ofFloat(expandedImageView,
+ View.Y,startBounds.top))
+ .with(ObjectAnimator
+ .ofFloat(expandedImageView,
+ View.SCALE_X, startScaleFinal))
+ .with(ObjectAnimator
+ .ofFloat(expandedImageView,
+ View.SCALE_Y, startScaleFinal));
+ set.setDuration(mShortAnimationDuration);
+ set.setInterpolator(new DecelerateInterpolator());
+ set.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ thumbView.setAlpha(1f);
+ expandedImageView.setVisibility(View.GONE);
+ mCurrentAnimator = null;
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ thumbView.setAlpha(1f);
+ expandedImageView.setVisibility(View.GONE);
+ mCurrentAnimator = null;
+ }
+ });
+ set.start();
+ mCurrentAnimator = set;
+ }
+ });
+}
+</pre>
\ No newline at end of file
diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs
index 4ad1353..4a5b0fa 100644
--- a/docs/html/training/training_toc.cs
+++ b/docs/html/training/training_toc.cs
@@ -287,6 +287,34 @@
</li>
</ul>
</li>
+
+ <li class="nav-section">
+ <div class="nav-section-header"><a href="<?cs var:toroot ?>training/animation/index.html">
+ <span class="en">Adding Animations</span>
+ </a></div>
+ <ul>
+ <li><a href="<?cs var:toroot ?>training/animation/crossfade.html">
+ <span class="en">Crossfading Two Views</span>
+ </a>
+ </li>
+ <li><a href="<?cs var:toroot ?>training/animation/screen-slide.html">
+ <span class="en">Using ViewPager for Screen Slide</span>
+ </a>
+ </li>
+ <li><a href="<?cs var:toroot ?>training/animation/cardflip.html">
+ <span class="en">Displaying Card Flip Animations</span>
+ </a>
+ </li>
+ <li><a href="<?cs var:toroot ?>training/animation/zoom.html">
+ <span class="en">Zooming a View</span>
+ </a>
+ </li>
+ <li><a href="<?cs var:toroot ?>training/animation/layout.html">
+ <span class="en">Animating Layout Changes</span>
+ </a>
+ </li>
+ </ul>
+ </li>
<li class="nav-section">
<div class="nav-section-header"><a href="<?cs var:toroot ?>training/managing-audio/index.html">