summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Nurik <romannurik@google.com>2012-10-15 13:09:16 -0700
committerRoman Nurik <romannurik@google.com>2012-10-25 12:59:24 -0700
commit01be9fd4c0ab5ed70b413f856d3f3a3367863a81 (patch)
tree603ae25571898821a529496ec797c77582bae5bd
parent6a705429d4a70d1d75adec16499bbcd18ee9a019 (diff)
downloaddevelopment-01be9fd4c0ab5ed70b413f856d3f3a3367863a81.tar.gz
AnimationsDemo sample code for Animations training class.
Change-Id: I0fbf3c2f66ee4321adcc0c0bf3fe7f4b4e67584e
-rwxr-xr-xsamples/training/AnimationsDemo/AndroidManifest.xml85
-rw-r--r--samples/training/AnimationsDemo/libs/android-support-v13.jarbin0 -> 350075 bytes
-rwxr-xr-xsamples/training/AnimationsDemo/project.properties11
-rw-r--r--samples/training/AnimationsDemo/res/animator/card_flip_left_in.xml60
-rw-r--r--samples/training/AnimationsDemo/res/animator/card_flip_left_out.xml52
-rw-r--r--samples/training/AnimationsDemo/res/animator/card_flip_right_in.xml60
-rw-r--r--samples/training/AnimationsDemo/res/animator/card_flip_right_out.xml52
-rw-r--r--samples/training/AnimationsDemo/res/drawable-hdpi/ic_action_info.pngbin0 -> 1629 bytes
-rw-r--r--samples/training/AnimationsDemo/res/drawable-hdpi/ic_action_new.pngbin0 -> 1142 bytes
-rw-r--r--samples/training/AnimationsDemo/res/drawable-hdpi/ic_action_photo.pngbin0 -> 1426 bytes
-rwxr-xr-xsamples/training/AnimationsDemo/res/drawable-hdpi/ic_launcher.pngbin0 -> 4283 bytes
-rw-r--r--samples/training/AnimationsDemo/res/drawable-hdpi/ic_list_remove.pngbin0 -> 1358 bytes
-rw-r--r--samples/training/AnimationsDemo/res/drawable-mdpi/ic_action_info.pngbin0 -> 1333 bytes
-rw-r--r--samples/training/AnimationsDemo/res/drawable-mdpi/ic_action_new.pngbin0 -> 1090 bytes
-rw-r--r--samples/training/AnimationsDemo/res/drawable-mdpi/ic_action_photo.pngbin0 -> 1240 bytes
-rwxr-xr-xsamples/training/AnimationsDemo/res/drawable-mdpi/ic_launcher.pngbin0 -> 2736 bytes
-rw-r--r--samples/training/AnimationsDemo/res/drawable-mdpi/ic_list_remove.pngbin0 -> 1202 bytes
-rw-r--r--samples/training/AnimationsDemo/res/drawable-nodpi/image1.pngbin0 -> 918363 bytes
-rw-r--r--samples/training/AnimationsDemo/res/drawable-nodpi/image2.pngbin0 -> 879429 bytes
-rw-r--r--samples/training/AnimationsDemo/res/drawable-nodpi/thumb1.pngbin0 -> 32591 bytes
-rw-r--r--samples/training/AnimationsDemo/res/drawable-nodpi/thumb2.pngbin0 -> 34275 bytes
-rw-r--r--samples/training/AnimationsDemo/res/drawable-xhdpi/ic_action_info.pngbin0 -> 2040 bytes
-rw-r--r--samples/training/AnimationsDemo/res/drawable-xhdpi/ic_action_new.pngbin0 -> 1221 bytes
-rw-r--r--samples/training/AnimationsDemo/res/drawable-xhdpi/ic_action_photo.pngbin0 -> 1544 bytes
-rwxr-xr-xsamples/training/AnimationsDemo/res/drawable-xhdpi/ic_launcher.pngbin0 -> 5702 bytes
-rw-r--r--samples/training/AnimationsDemo/res/drawable-xhdpi/ic_list_remove.pngbin0 -> 1488 bytes
-rwxr-xr-xsamples/training/AnimationsDemo/res/layout/activity_card_flip.xml20
-rw-r--r--samples/training/AnimationsDemo/res/layout/activity_crossfade.xml33
-rw-r--r--samples/training/AnimationsDemo/res/layout/activity_layout_changes.xml51
-rwxr-xr-xsamples/training/AnimationsDemo/res/layout/activity_main.xml22
-rwxr-xr-xsamples/training/AnimationsDemo/res/layout/activity_screen_slide.xml20
-rw-r--r--samples/training/AnimationsDemo/res/layout/activity_zoom.xml79
-rw-r--r--samples/training/AnimationsDemo/res/layout/excerpt_content.xml31
-rw-r--r--samples/training/AnimationsDemo/res/layout/fragment_card_back.xml42
-rw-r--r--samples/training/AnimationsDemo/res/layout/fragment_card_front.xml22
-rw-r--r--samples/training/AnimationsDemo/res/layout/fragment_screen_slide_page.xml43
-rw-r--r--samples/training/AnimationsDemo/res/layout/list_item_example.xml42
-rw-r--r--samples/training/AnimationsDemo/res/menu/activity_crossfade.xml25
-rw-r--r--samples/training/AnimationsDemo/res/menu/activity_layout_changes.xml25
-rw-r--r--samples/training/AnimationsDemo/res/menu/activity_screen_slide.xml24
-rw-r--r--samples/training/AnimationsDemo/res/values/ids.xml29
-rw-r--r--samples/training/AnimationsDemo/res/values/integers.xml20
-rwxr-xr-xsamples/training/AnimationsDemo/res/values/strings.xml53
-rw-r--r--samples/training/AnimationsDemo/res/values/styles.xml25
-rw-r--r--samples/training/AnimationsDemo/src/com/example/android/animationsdemo/CardFlipActivity.java191
-rw-r--r--samples/training/AnimationsDemo/src/com/example/android/animationsdemo/CrossfadeActivity.java137
-rw-r--r--samples/training/AnimationsDemo/src/com/example/android/animationsdemo/LayoutChangesActivity.java117
-rwxr-xr-xsamples/training/AnimationsDemo/src/com/example/android/animationsdemo/MainActivity.java82
-rw-r--r--samples/training/AnimationsDemo/src/com/example/android/animationsdemo/ScreenSlideActivity.java141
-rw-r--r--samples/training/AnimationsDemo/src/com/example/android/animationsdemo/ScreenSlidePageFragment.java84
-rw-r--r--samples/training/AnimationsDemo/src/com/example/android/animationsdemo/TouchHighlightImageButton.java109
-rw-r--r--samples/training/AnimationsDemo/src/com/example/android/animationsdemo/ZoomActivity.java233
52 files changed, 2020 insertions, 0 deletions
diff --git a/samples/training/AnimationsDemo/AndroidManifest.xml b/samples/training/AnimationsDemo/AndroidManifest.xml
new file mode 100755
index 000000000..dcb911a12
--- /dev/null
+++ b/samples/training/AnimationsDemo/AndroidManifest.xml
@@ -0,0 +1,85 @@
+<!--
+ Copyright 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.animationsdemo"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <!--
+ This example's minimum API level is 14 due to the following recent
+ key platform features:
+
+ API 11: property animations (android.animations package)
+ API 12: ViewPropertyAnimator
+ API 14: View properties (android.util.Property) such as View.X and View.Y.
+ -->
+ <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="17" />
+
+ <application android:allowBackup="true"
+ android:label="@string/app_name"
+ android:icon="@drawable/ic_launcher"
+ android:theme="@android:style/Theme.Holo.Light.DarkActionBar">
+
+ <activity android:name=".MainActivity"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".CrossfadeActivity"
+ android:label="@string/title_crossfade"
+ android:uiOptions="splitActionBarWhenNarrow"
+ android:parentActivityName=".MainActivity">
+ <meta-data android:name="android.support.PARENT_ACTIVITY"
+ android:value=".MainActivity" />
+ </activity>
+
+ <activity android:name=".CardFlipActivity"
+ android:label="@string/title_card_flip"
+ android:parentActivityName=".MainActivity"
+ android:theme="@style/DarkTheme">
+ <meta-data android:name="android.support.PARENT_ACTIVITY"
+ android:value=".MainActivity" />
+ </activity>
+
+ <activity android:name=".ScreenSlideActivity"
+ android:label="@string/title_screen_slide"
+ android:parentActivityName=".MainActivity"
+ android:uiOptions="splitActionBarWhenNarrow">
+ <meta-data android:name="android.support.PARENT_ACTIVITY"
+ android:value=".MainActivity" />
+ </activity>
+
+ <activity android:name=".ZoomActivity"
+ android:label="@string/title_zoom"
+ android:parentActivityName=".MainActivity">
+ <meta-data android:name="android.support.PARENT_ACTIVITY"
+ android:value=".MainActivity" />
+ </activity>
+
+ <activity android:name=".LayoutChangesActivity"
+ android:label="@string/title_layout_changes"
+ android:parentActivityName=".MainActivity">>
+ <meta-data android:name="android.support.PARENT_ACTIVITY"
+ android:value=".MainActivity" />
+ </activity>
+
+ </application>
+
+</manifest>
diff --git a/samples/training/AnimationsDemo/libs/android-support-v13.jar b/samples/training/AnimationsDemo/libs/android-support-v13.jar
new file mode 100644
index 000000000..df7f9fc24
--- /dev/null
+++ b/samples/training/AnimationsDemo/libs/android-support-v13.jar
Binary files differ
diff --git a/samples/training/AnimationsDemo/project.properties b/samples/training/AnimationsDemo/project.properties
new file mode 100755
index 000000000..895c9ce2e
--- /dev/null
+++ b/samples/training/AnimationsDemo/project.properties
@@ -0,0 +1,11 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-16
diff --git a/samples/training/AnimationsDemo/res/animator/card_flip_left_in.xml b/samples/training/AnimationsDemo/res/animator/card_flip_left_in.xml
new file mode 100644
index 000000000..1a105f148
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/animator/card_flip_left_in.xml
@@ -0,0 +1,60 @@
+<!--
+ Copyright 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<!--
+ This object animator is used as a custom fragment transition. See
+ FragmentTransaction.setCustomAnimation for more details.
+
+ The overall effect of this animator is to rotate the back of the card
+ into view. The order of operations is described below:
+
+ 1. The back is immediately set to transparent.
+ 2. The invisible back rotates 90 degrees, from being fully flipped
+ to being zero-width, fully perpendicular to the viewer, facing right.
+ It is still invisible.
+ 3. The back is then made visible (this is half-way through the
+ animation).
+ 4. The back rotates another 90 degrees, from zero-width, to
+ 100% of its normal width, facing the user.
+
+ This is accomplished using the 3 child animators below, executed in
+ parallel. Note that the last animator starts half-way into the animation.
+-->
+
+<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>
diff --git a/samples/training/AnimationsDemo/res/animator/card_flip_left_out.xml b/samples/training/AnimationsDemo/res/animator/card_flip_left_out.xml
new file mode 100644
index 000000000..2de7e9593
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/animator/card_flip_left_out.xml
@@ -0,0 +1,52 @@
+<!--
+ Copyright 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<!--
+ This object animator is used as a custom fragment transition. See
+ FragmentTransaction.setCustomAnimation for more details.
+
+ The overall effect of this animator is to rotate the front of the card
+ out of view. The order of operations is described below:
+
+ 1. The front rotates 90 degrees, from facing the user to being
+ zero-width, fully perpendicular to the viewer, facing left.
+ 2. The front is then made invisible (this is half-way through the
+ animation).
+ 3. The front rotates another 90 degrees, from zero-width, to
+ 100% of its normal width, but facing away from the user and
+ still invisible.
+
+ This is accomplished using the 2 child animators below, executed in
+ parallel. Note that the last animator starts half-way into the animation.
+-->
+
+<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>
diff --git a/samples/training/AnimationsDemo/res/animator/card_flip_right_in.xml b/samples/training/AnimationsDemo/res/animator/card_flip_right_in.xml
new file mode 100644
index 000000000..8fe41732c
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/animator/card_flip_right_in.xml
@@ -0,0 +1,60 @@
+<!--
+ Copyright 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<!--
+ This object animator is used as a custom fragment transition. See
+ FragmentTransaction.setCustomAnimation for more details.
+
+ The overall effect of this animator is to rotate the front of the card
+ into view. The order of operations is described below:
+
+ 1. The front is immediately set to transparent.
+ 2. The invisible front rotates 90 degrees, from being fully flipped
+ to being zero-width, fully perpendicular to the viewer, facing left.
+ It is still invisible.
+ 3. The front is then made visible (this is half-way through the
+ animation).
+ 4. The front rotates another 90 degrees, from zero-width, to
+ 100% of its normal width, facing the user.
+
+ This is accomplished using the 3 child animators below, executed in
+ parallel. Note that the last animator starts half-way into the animation.
+-->
+
+<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>
diff --git a/samples/training/AnimationsDemo/res/animator/card_flip_right_out.xml b/samples/training/AnimationsDemo/res/animator/card_flip_right_out.xml
new file mode 100644
index 000000000..099db6c56
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/animator/card_flip_right_out.xml
@@ -0,0 +1,52 @@
+<!--
+ Copyright 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<!--
+ This object animator is used as a custom fragment transition. See
+ FragmentTransaction.setCustomAnimation for more details.
+
+ The overall effect of this animator is to rotate the back of the card
+ out of view. The order of operations is described below:
+
+ 1. The back rotates 90 degrees, from facing the user to being
+ zero-width, fully perpendicular to the viewer, facing right.
+ 2. The back is then made invisible (this is half-way through the
+ animation).
+ 3. The back rotates another 90 degrees, from zero-width, to
+ 100% of its normal width, but facing away from the user and
+ still invisible.
+
+ This is accomplished using the 2 child animators below, executed in
+ parallel. Note that the last animator starts half-way into the animation.
+-->
+
+<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>
diff --git a/samples/training/AnimationsDemo/res/drawable-hdpi/ic_action_info.png b/samples/training/AnimationsDemo/res/drawable-hdpi/ic_action_info.png
new file mode 100644
index 000000000..6eaf08aec
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/drawable-hdpi/ic_action_info.png
Binary files differ
diff --git a/samples/training/AnimationsDemo/res/drawable-hdpi/ic_action_new.png b/samples/training/AnimationsDemo/res/drawable-hdpi/ic_action_new.png
new file mode 100644
index 000000000..ad8ada6bd
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/drawable-hdpi/ic_action_new.png
Binary files differ
diff --git a/samples/training/AnimationsDemo/res/drawable-hdpi/ic_action_photo.png b/samples/training/AnimationsDemo/res/drawable-hdpi/ic_action_photo.png
new file mode 100644
index 000000000..0f650ee25
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/drawable-hdpi/ic_action_photo.png
Binary files differ
diff --git a/samples/training/AnimationsDemo/res/drawable-hdpi/ic_launcher.png b/samples/training/AnimationsDemo/res/drawable-hdpi/ic_launcher.png
new file mode 100755
index 000000000..9c8635efe
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/training/AnimationsDemo/res/drawable-hdpi/ic_list_remove.png b/samples/training/AnimationsDemo/res/drawable-hdpi/ic_list_remove.png
new file mode 100644
index 000000000..cde36e1fa
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/drawable-hdpi/ic_list_remove.png
Binary files differ
diff --git a/samples/training/AnimationsDemo/res/drawable-mdpi/ic_action_info.png b/samples/training/AnimationsDemo/res/drawable-mdpi/ic_action_info.png
new file mode 100644
index 000000000..d7b7e6986
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/drawable-mdpi/ic_action_info.png
Binary files differ
diff --git a/samples/training/AnimationsDemo/res/drawable-mdpi/ic_action_new.png b/samples/training/AnimationsDemo/res/drawable-mdpi/ic_action_new.png
new file mode 100644
index 000000000..4d5d484b3
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/drawable-mdpi/ic_action_new.png
Binary files differ
diff --git a/samples/training/AnimationsDemo/res/drawable-mdpi/ic_action_photo.png b/samples/training/AnimationsDemo/res/drawable-mdpi/ic_action_photo.png
new file mode 100644
index 000000000..d6235554b
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/drawable-mdpi/ic_action_photo.png
Binary files differ
diff --git a/samples/training/AnimationsDemo/res/drawable-mdpi/ic_launcher.png b/samples/training/AnimationsDemo/res/drawable-mdpi/ic_launcher.png
new file mode 100755
index 000000000..2497b0986
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/training/AnimationsDemo/res/drawable-mdpi/ic_list_remove.png b/samples/training/AnimationsDemo/res/drawable-mdpi/ic_list_remove.png
new file mode 100644
index 000000000..9f4c3d6a2
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/drawable-mdpi/ic_list_remove.png
Binary files differ
diff --git a/samples/training/AnimationsDemo/res/drawable-nodpi/image1.png b/samples/training/AnimationsDemo/res/drawable-nodpi/image1.png
new file mode 100644
index 000000000..6606479e7
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/drawable-nodpi/image1.png
Binary files differ
diff --git a/samples/training/AnimationsDemo/res/drawable-nodpi/image2.png b/samples/training/AnimationsDemo/res/drawable-nodpi/image2.png
new file mode 100644
index 000000000..ab3a52fff
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/drawable-nodpi/image2.png
Binary files differ
diff --git a/samples/training/AnimationsDemo/res/drawable-nodpi/thumb1.png b/samples/training/AnimationsDemo/res/drawable-nodpi/thumb1.png
new file mode 100644
index 000000000..245d5ad20
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/drawable-nodpi/thumb1.png
Binary files differ
diff --git a/samples/training/AnimationsDemo/res/drawable-nodpi/thumb2.png b/samples/training/AnimationsDemo/res/drawable-nodpi/thumb2.png
new file mode 100644
index 000000000..573397c10
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/drawable-nodpi/thumb2.png
Binary files differ
diff --git a/samples/training/AnimationsDemo/res/drawable-xhdpi/ic_action_info.png b/samples/training/AnimationsDemo/res/drawable-xhdpi/ic_action_info.png
new file mode 100644
index 000000000..4ee903f07
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/drawable-xhdpi/ic_action_info.png
Binary files differ
diff --git a/samples/training/AnimationsDemo/res/drawable-xhdpi/ic_action_new.png b/samples/training/AnimationsDemo/res/drawable-xhdpi/ic_action_new.png
new file mode 100644
index 000000000..23b9a1c18
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/drawable-xhdpi/ic_action_new.png
Binary files differ
diff --git a/samples/training/AnimationsDemo/res/drawable-xhdpi/ic_action_photo.png b/samples/training/AnimationsDemo/res/drawable-xhdpi/ic_action_photo.png
new file mode 100644
index 000000000..3f93e4f65
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/drawable-xhdpi/ic_action_photo.png
Binary files differ
diff --git a/samples/training/AnimationsDemo/res/drawable-xhdpi/ic_launcher.png b/samples/training/AnimationsDemo/res/drawable-xhdpi/ic_launcher.png
new file mode 100755
index 000000000..017ced125
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/training/AnimationsDemo/res/drawable-xhdpi/ic_list_remove.png b/samples/training/AnimationsDemo/res/drawable-xhdpi/ic_list_remove.png
new file mode 100644
index 000000000..ca7d159fd
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/drawable-xhdpi/ic_list_remove.png
Binary files differ
diff --git a/samples/training/AnimationsDemo/res/layout/activity_card_flip.xml b/samples/training/AnimationsDemo/res/layout/activity_card_flip.xml
new file mode 100755
index 000000000..30d659fe1
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/layout/activity_card_flip.xml
@@ -0,0 +1,20 @@
+<!--
+ Copyright 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
diff --git a/samples/training/AnimationsDemo/res/layout/activity_crossfade.xml b/samples/training/AnimationsDemo/res/layout/activity_crossfade.xml
new file mode 100644
index 000000000..819e03daf
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/layout/activity_crossfade.xml
@@ -0,0 +1,33 @@
+<!--
+ Copyright 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <!-- Contains the "content" view and its children. -->
+ <include layout="@layout/excerpt_content" />
+
+ <!-- The "loading indicator" view. This view overlaps with
+ the content, so the visibility of these two views
+ should be mutually exclusive. -->
+ <ProgressBar android:id="@+id/loading_spinner"
+ style="?android:progressBarStyleLarge"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center" />
+
+</FrameLayout>
diff --git a/samples/training/AnimationsDemo/res/layout/activity_layout_changes.xml b/samples/training/AnimationsDemo/res/layout/activity_layout_changes.xml
new file mode 100644
index 000000000..1758cd648
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/layout/activity_layout_changes.xml
@@ -0,0 +1,51 @@
+<!--
+ Copyright 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <!-- A vertical LinearLayout in a ScrollView. This emulates a ListView (and is lighter weight
+ than a ListView when there aren't many rows). -->
+ <ScrollView android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <!-- Note that this LinearLayout has the "animateLayoutChanges" property set to true.
+ This tells the framework to automatically animate child views (in this case, rows)
+ as they are added to and removed from the LinearLayout. -->
+ <LinearLayout android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:showDividers="middle"
+ android:divider="?android:dividerHorizontal"
+ android:animateLayoutChanges="true"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp" />
+
+ </ScrollView>
+
+ <!-- The "empty" view to show when there are no items in the "list" view defined above. -->
+ <TextView android:id="@android:id/empty"
+ style="?android:textAppearanceSmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:padding="32dp"
+ android:text="@string/message_empty_layout_changes"
+ android:textColor="?android:textColorSecondary" />
+
+</FrameLayout>
diff --git a/samples/training/AnimationsDemo/res/layout/activity_main.xml b/samples/training/AnimationsDemo/res/layout/activity_main.xml
new file mode 100755
index 000000000..b33be1fe8
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/layout/activity_main.xml
@@ -0,0 +1,22 @@
+<!--
+ Copyright 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<ListView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@android:id/list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp" />
diff --git a/samples/training/AnimationsDemo/res/layout/activity_screen_slide.xml b/samples/training/AnimationsDemo/res/layout/activity_screen_slide.xml
new file mode 100755
index 000000000..339b592d5
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/layout/activity_screen_slide.xml
@@ -0,0 +1,20 @@
+<!--
+ Copyright 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<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" />
diff --git a/samples/training/AnimationsDemo/res/layout/activity_zoom.xml b/samples/training/AnimationsDemo/res/layout/activity_zoom.xml
new file mode 100644
index 000000000..712dc6143
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/layout/activity_zoom.xml
@@ -0,0 +1,79 @@
+<!--
+ Copyright 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<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">
+
+ <TextView style="?android:textAppearanceSmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/message_zoom_touch_expand" />
+
+ <!-- This is an example layout containing thumbnail image buttons that, when pressed,
+ zoom in to show more detail. All of the zooming and animation logic is in
+ the ZoomActivity class. -->
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:orientation="horizontal">
+
+ <!-- These buttons don't have any decorations (3D bevel, etc.), but it's still
+ important to show feedback on touch or focus. The custom
+ "ToughHighlightImageButton" ImageButton subclass helps achieve this by drawing
+ the standard system "pressed" and "focused" overlay upon user interaction. -->
+
+ <com.example.android.animationsdemo.TouchHighlightImageButton
+ 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" />
+
+ <com.example.android.animationsdemo.TouchHighlightImageButton
+ android:id="@+id/thumb_button_2"
+ android:layout_width="100dp"
+ android:layout_height="75dp"
+ android:src="@drawable/thumb2"
+ android:scaleType="centerCrop"
+ android:contentDescription="@string/description_image_2" />
+
+ </LinearLayout>
+
+ </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 buttons above, to its final laid-out bounds. The implementation
+ of this animation is in the ZoomActivity class. -->
+ <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>
diff --git a/samples/training/AnimationsDemo/res/layout/excerpt_content.xml b/samples/training/AnimationsDemo/res/layout/excerpt_content.xml
new file mode 100644
index 000000000..0237f2bad
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/layout/excerpt_content.xml
@@ -0,0 +1,31 @@
+<!--
+ Copyright 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <!-- Dummy content. -->
+ <TextView style="?android:textAppearanceMedium"
+ android:lineSpacingMultiplier="1.2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/lorem_ipsum"
+ android:textIsSelectable="true"
+ android:padding="16dp" />
+
+</ScrollView>
diff --git a/samples/training/AnimationsDemo/res/layout/fragment_card_back.xml b/samples/training/AnimationsDemo/res/layout/fragment_card_back.xml
new file mode 100644
index 000000000..39bd784cf
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/layout/fragment_card_back.xml
@@ -0,0 +1,42 @@
+<!--
+ Copyright 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<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>
diff --git a/samples/training/AnimationsDemo/res/layout/fragment_card_front.xml b/samples/training/AnimationsDemo/res/layout/fragment_card_front.xml
new file mode 100644
index 000000000..e887c14a8
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/layout/fragment_card_front.xml
@@ -0,0 +1,22 @@
+<!--
+ Copyright 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<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" />
diff --git a/samples/training/AnimationsDemo/res/layout/fragment_screen_slide_page.xml b/samples/training/AnimationsDemo/res/layout/fragment_screen_slide_page.xml
new file mode 100644
index 000000000..8aa472b87
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/layout/fragment_screen_slide_page.xml
@@ -0,0 +1,43 @@
+<!--
+ Copyright 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <!-- Dummy content. -->
+ <LinearLayout android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:padding="16dp">
+
+ <TextView android:id="@android:id/text1"
+ style="?android:textAppearanceLarge"
+ android:textStyle="bold"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="16dp" />
+
+ <TextView style="?android:textAppearanceMedium"
+ android:lineSpacingMultiplier="1.2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/lorem_ipsum" />
+
+ </LinearLayout>
+
+</ScrollView>
diff --git a/samples/training/AnimationsDemo/res/layout/list_item_example.xml b/samples/training/AnimationsDemo/res/layout/list_item_example.xml
new file mode 100644
index 000000000..3822932e3
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/layout/list_item_example.xml
@@ -0,0 +1,42 @@
+<!--
+ Copyright 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="?android:listPreferredItemHeightSmall"
+ android:orientation="horizontal"
+ android:showDividers="middle"
+ android:divider="?android:dividerVertical"
+ android:dividerPadding="8dp"
+ android:gravity="center">
+
+ <!-- Dummy text view that will display the name of a random country. -->
+ <TextView android:id="@android:id/text1"
+ style="?android:textAppearanceMedium"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:layout_height="wrap_content"
+ android:paddingLeft="?android:listPreferredItemPaddingLeft" />
+
+ <!-- A button that, when pressed, will delete this list item row from its container. -->
+ <ImageButton android:id="@+id/delete_button"
+ android:layout_width="48dp"
+ android:layout_height="match_parent"
+ android:src="@drawable/ic_list_remove"
+ android:background="?android:selectableItemBackground"
+ android:contentDescription="@string/action_remove_item" />
+
+</LinearLayout>
diff --git a/samples/training/AnimationsDemo/res/menu/activity_crossfade.xml b/samples/training/AnimationsDemo/res/menu/activity_crossfade.xml
new file mode 100644
index 000000000..bb21a3838
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/menu/activity_crossfade.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <!-- Toggles between a content view and a loading indicator view. Real-world
+ applications should automatically toggle when content becomes available. -->
+ <item android:id="@+id/action_toggle"
+ android:title="@string/action_toggle"
+ android:showAsAction="ifRoom|withText" />
+
+</menu>
diff --git a/samples/training/AnimationsDemo/res/menu/activity_layout_changes.xml b/samples/training/AnimationsDemo/res/menu/activity_layout_changes.xml
new file mode 100644
index 000000000..e919ae0df
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/menu/activity_layout_changes.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <!-- Adds an item to the list. -->
+ <item android:id="@+id/action_add_item"
+ android:title="@string/action_add_item"
+ android:icon="@drawable/ic_action_new"
+ android:showAsAction="ifRoom" />
+
+</menu>
diff --git a/samples/training/AnimationsDemo/res/menu/activity_screen_slide.xml b/samples/training/AnimationsDemo/res/menu/activity_screen_slide.xml
new file mode 100644
index 000000000..7e31b34e8
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/menu/activity_screen_slide.xml
@@ -0,0 +1,24 @@
+<!--
+ Copyright 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <!-- Adds an item to the list. -->
+ <item android:id="@+id/action_previous"
+ android:title="@string/action_previous"
+ android:showAsAction="ifRoom|withText" />
+
+</menu>
diff --git a/samples/training/AnimationsDemo/res/values/ids.xml b/samples/training/AnimationsDemo/res/values/ids.xml
new file mode 100644
index 000000000..bbc0ecedb
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/values/ids.xml
@@ -0,0 +1,29 @@
+<!--
+ Copyright 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources>
+
+ <!--
+ These action bar item IDs (menu item IDs) are defined here for
+ programmatic use. Normally, IDs are created using the "@+id/foo"
+ syntax, but since these IDs aren't created in menu XML, rather
+ used for programmatically-instantiated action bar items, they
+ are defined here.
+ -->
+ <item type="id" name="action_next" />
+ <item type="id" name="action_flip" />
+
+</resources>
diff --git a/samples/training/AnimationsDemo/res/values/integers.xml b/samples/training/AnimationsDemo/res/values/integers.xml
new file mode 100644
index 000000000..bf09638eb
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/values/integers.xml
@@ -0,0 +1,20 @@
+<!--
+ Copyright 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources>
+ <integer name="card_flip_time_full">300</integer>
+ <integer name="card_flip_time_half">150</integer>
+</resources>
diff --git a/samples/training/AnimationsDemo/res/values/strings.xml b/samples/training/AnimationsDemo/res/values/strings.xml
new file mode 100755
index 000000000..7d41cd8b7
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/values/strings.xml
@@ -0,0 +1,53 @@
+<!--
+ Copyright 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- Titles -->
+ <string name="app_name">Animations Demo</string>
+ <string name="title_crossfade">Simple Crossfade</string>
+ <string name="title_card_flip">Card Flip</string>
+ <string name="title_screen_slide">Screen Slide</string>
+ <string name="title_zoom">Zoom</string>
+ <string name="title_layout_changes">Layout Changes</string>
+ <string name="title_template_step">Step <xliff:g id="step_number">%1$d</xliff:g>: Lorem
+ Ipsum</string>
+
+ <!-- Actions -->
+ <string name="action_toggle">Toggle indicator</string>
+ <string name="action_add_item">Add item</string>
+ <string name="action_remove_item">Remove item</string>
+ <string name="action_previous">Previous</string>
+ <string name="action_next">Next</string>
+ <string name="action_finish">Finish</string>
+ <string name="action_info">Photo info</string>
+ <string name="action_photo">View photo</string>
+
+ <!-- Messages -->
+ <string name="message_empty_layout_changes">Add an item above to get started.</string>
+ <string name="message_zoom_touch_expand">Touch a photo to expand it.</string>
+
+ <!-- Accessibility-only descriptions -->
+ <string name="description_image_1">Image 1</string>
+ <string name="description_image_2">Image 2</string>
+ <string name="description_zoom_touch_close">Expanded image (touch to close)</string>
+
+ <!-- Other strings -->
+ <string name="card_back_title">Angry Red Android</string>
+ <string name="card_back_description"><![CDATA[Lorem ipsum dolor sit]]></string>
+ <string name="lorem_ipsum"><![CDATA[Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris et magna ut erat elementum cursus in quis ipsum. Nam faucibus ultrices eros, vel tempor leo semper sit amet. Duis magna quam, congue vitae interdum nec, condimentum ut lectus. Sed commodo venenatis eros a dignissim. Nunc adipiscing turpis nec magna venenatis at ultricies ipsum bibendum. Sed volutpat urna quis nisi vulputate egestas. Etiam eu dui a enim lacinia dapibus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.\n\nPhasellus orci mi, eleifend nec congue id, volutpat at neque. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Integer semper velit vel leo rutrum sed fermentum elit porta.]]></string>
+
+</resources>
diff --git a/samples/training/AnimationsDemo/res/values/styles.xml b/samples/training/AnimationsDemo/res/values/styles.xml
new file mode 100644
index 000000000..56d30db44
--- /dev/null
+++ b/samples/training/AnimationsDemo/res/values/styles.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources>
+ <style name="DarkTheme" parent="android:Theme.Holo">
+ <item name="android:actionBarStyle">@style/DarkActionBar</item>
+ </style>
+
+ <style name="DarkActionBar" parent="android:Widget.Holo.ActionBar">
+ <item name="android:background">@android:color/transparent</item>
+ </style>
+</resources>
diff --git a/samples/training/AnimationsDemo/src/com/example/android/animationsdemo/CardFlipActivity.java b/samples/training/AnimationsDemo/src/com/example/android/animationsdemo/CardFlipActivity.java
new file mode 100644
index 000000000..f091d37dc
--- /dev/null
+++ b/samples/training/AnimationsDemo/src/com/example/android/animationsdemo/CardFlipActivity.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.animationsdemo;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.v4.app.NavUtils;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+/**
+ * Demonstrates a "card-flip" animation using custom fragment transactions ({@link
+ * android.app.FragmentTransaction#setCustomAnimations(int, int)}).
+ *
+ * <p>This sample shows an "info" action bar button that shows the back of a "card", rotating the
+ * front of the card out and the back of the card in. The reverse animation is played when the user
+ * presses the system Back button or the "photo" action bar button.</p>
+ */
+public class CardFlipActivity extends Activity
+ implements FragmentManager.OnBackStackChangedListener {
+ /**
+ * A handler object, used for deferring UI operations.
+ */
+ private Handler mHandler = new Handler();
+
+ /**
+ * Whether or not we're showing the back of the card (otherwise showing the front).
+ */
+ private boolean mShowingBack = false;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_card_flip);
+
+ if (savedInstanceState == null) {
+ // If there is no saved instance state, add a fragment representing the
+ // front of the card to this activity. If there is saved instance state,
+ // this fragment will have already been added to the activity.
+ getFragmentManager()
+ .beginTransaction()
+ .add(R.id.container, new CardFrontFragment())
+ .commit();
+ } else {
+ mShowingBack = (getFragmentManager().getBackStackEntryCount() > 0);
+ }
+
+ // Monitor back stack changes to ensure the action bar shows the appropriate
+ // button (either "photo" or "info").
+ getFragmentManager().addOnBackStackChangedListener(this);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+
+ // Add either a "photo" or "finish" button to the action bar, depending on which page
+ // is currently selected.
+ MenuItem item = menu.add(Menu.NONE, R.id.action_flip, Menu.NONE,
+ mShowingBack
+ ? R.string.action_photo
+ : R.string.action_info);
+ item.setIcon(mShowingBack
+ ? R.drawable.ic_action_photo
+ : R.drawable.ic_action_info);
+ item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ // Navigate "up" the demo structure to the launchpad activity.
+ // See http://developer.android.com/design/patterns/navigation.html for more.
+ NavUtils.navigateUpTo(this, new Intent(this, MainActivity.class));
+ return true;
+
+ case R.id.action_flip:
+ flipCard();
+ return true;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ 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();
+
+ // Defer an invalidation of the options menu (on modern devices, the action bar). This
+ // can't be done immediately because the transaction may not yet be committed. Commits
+ // are asynchronous in that they are posted to the main thread's message loop.
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ invalidateOptionsMenu();
+ }
+ });
+ }
+
+ @Override
+ public void onBackStackChanged() {
+ mShowingBack = (getFragmentManager().getBackStackEntryCount() > 0);
+
+ // When the back stack changes, invalidate the options menu (action bar).
+ invalidateOptionsMenu();
+ }
+
+ /**
+ * A fragment representing the front of the card.
+ */
+ public static class CardFrontFragment extends Fragment {
+ public CardFrontFragment() {
+ }
+
+ @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 static class CardBackFragment extends Fragment {
+ public CardBackFragment() {
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.fragment_card_back, container, false);
+ }
+ }
+}
diff --git a/samples/training/AnimationsDemo/src/com/example/android/animationsdemo/CrossfadeActivity.java b/samples/training/AnimationsDemo/src/com/example/android/animationsdemo/CrossfadeActivity.java
new file mode 100644
index 000000000..b0f2509f8
--- /dev/null
+++ b/samples/training/AnimationsDemo/src/com/example/android/animationsdemo/CrossfadeActivity.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.animationsdemo;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v4.app.NavUtils;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+
+/**
+ * This sample demonstrates cross-fading between two overlapping views.
+ *
+ * <p>In this sample, the two overlapping views are a loading indicator and some text content. The
+ * active view is toggled by touching the toggle button in the action bar. In real-world
+ * applications, this toggle would occur as soon as content was available. Note that if content is
+ * immediately available, a loading spinner shouldn't be presented and there should be no
+ * animation.</p>
+ */
+public class CrossfadeActivity extends Activity {
+ /**
+ * The flag indicating whether content is loaded (text is shown) or not (loading spinner is
+ * shown).
+ */
+ private boolean mContentLoaded;
+
+ /**
+ * The view (or view group) containing the content. This is one of two overlapping views.
+ */
+ private View mContentView;
+
+ /**
+ * The view containing the loading indicator. This is the other of two overlapping views.
+ */
+ private View mLoadingView;
+
+ /**
+ * 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_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);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ getMenuInflater().inflate(R.menu.activity_crossfade, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ // Navigate "up" the demo structure to the launchpad activity.
+ // See http://developer.android.com/design/patterns/navigation.html for more.
+ NavUtils.navigateUpTo(this, new Intent(this, MainActivity.class));
+ return true;
+
+ case R.id.action_toggle:
+ // Toggle whether content is loaded.
+ mContentLoaded = !mContentLoaded;
+ showContentOrLoadingIndicator(mContentLoaded);
+ return true;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ /**
+ * Cross-fades between {@link #mContentView} and {@link #mLoadingView}.
+ */
+ private void showContentOrLoadingIndicator(boolean contentLoaded) {
+ // Decide which view to hide and which to show.
+ final View showView = contentLoaded ? mContentView : mLoadingView;
+ final View hideView = contentLoaded ? mLoadingView : mContentView;
+
+ // Set the "show" view to 0% opacity but visible, so that it is visible
+ // (but fully transparent) during the animation.
+ showView.setAlpha(0f);
+ showView.setVisibility(View.VISIBLE);
+
+ // Animate the "show" view to 100% opacity, and clear any animation listener set on
+ // the view. Remember that listeners are not limited to the specific animation
+ // describes in the chained method calls. Listeners are set on the
+ // ViewPropertyAnimator object for the view, which persists across several
+ // animations.
+ showView.animate()
+ .alpha(1f)
+ .setDuration(mShortAnimationDuration)
+ .setListener(null);
+
+ // Animate the "hide" 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.)
+ hideView.animate()
+ .alpha(0f)
+ .setDuration(mShortAnimationDuration)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ hideView.setVisibility(View.GONE);
+ }
+ });
+ }
+}
diff --git a/samples/training/AnimationsDemo/src/com/example/android/animationsdemo/LayoutChangesActivity.java b/samples/training/AnimationsDemo/src/com/example/android/animationsdemo/LayoutChangesActivity.java
new file mode 100644
index 000000000..42e3475a1
--- /dev/null
+++ b/samples/training/AnimationsDemo/src/com/example/android/animationsdemo/LayoutChangesActivity.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.animationsdemo;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v4.app.NavUtils;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+/**
+ * This sample demonstrates how to use system-provided, automatic layout transitions. Layout
+ * transitions are animations that occur when views are added to, removed from, or changed within
+ * a {@link ViewGroup}.
+ *
+ * <p>In this sample, the user can add rows to and remove rows from a vertical
+ * {@link android.widget.LinearLayout}.</p>
+ */
+public class LayoutChangesActivity extends Activity {
+ /**
+ * The container view which has layout change animations turned on. In this sample, this view
+ * is a {@link android.widget.LinearLayout}.
+ */
+ private ViewGroup mContainerView;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_layout_changes);
+
+ mContainerView = (ViewGroup) findViewById(R.id.container);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ getMenuInflater().inflate(R.menu.activity_layout_changes, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ // Navigate "up" the demo structure to the launchpad activity.
+ // See http://developer.android.com/design/patterns/navigation.html for more.
+ NavUtils.navigateUpTo(this, new Intent(this, MainActivity.class));
+ return true;
+
+ case R.id.action_add_item:
+ // Hide the "empty" view since there is now at least one item in the list.
+ findViewById(android.R.id.empty).setVisibility(View.GONE);
+ addItem();
+ return true;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ private void addItem() {
+ // Instantiate a new "row" view.
+ final ViewGroup newView = (ViewGroup) LayoutInflater.from(this).inflate(
+ R.layout.list_item_example, mContainerView, false);
+
+ // Set the text in the new row to a random country.
+ ((TextView) newView.findViewById(android.R.id.text1)).setText(
+ COUNTRIES[(int) (Math.random() * COUNTRIES.length)]);
+
+ // Set a click listener for the "X" button in the row that will remove the row.
+ newView.findViewById(R.id.delete_button).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ // Remove the row from its parent (the container view).
+ // Because mContainerView has android:animateLayoutChanges set to true,
+ // this removal is automatically animated.
+ mContainerView.removeView(newView);
+
+ // If there are no rows remaining, show the empty view.
+ if (mContainerView.getChildCount() == 0) {
+ findViewById(android.R.id.empty).setVisibility(View.VISIBLE);
+ }
+ }
+ });
+
+ // Because mContainerView has android:animateLayoutChanges set to true,
+ // adding this view is automatically animated.
+ mContainerView.addView(newView, 0);
+ }
+
+ /**
+ * A static list of country names.
+ */
+ private static final String[] COUNTRIES = new String[]{
+ "Belgium", "France", "Italy", "Germany", "Spain",
+ "Austria", "Russia", "Poland", "Croatia", "Greece",
+ "Ukraine",
+ };
+}
diff --git a/samples/training/AnimationsDemo/src/com/example/android/animationsdemo/MainActivity.java b/samples/training/AnimationsDemo/src/com/example/android/animationsdemo/MainActivity.java
new file mode 100755
index 000000000..5d4802a05
--- /dev/null
+++ b/samples/training/AnimationsDemo/src/com/example/android/animationsdemo/MainActivity.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.animationsdemo;
+
+import android.app.Activity;
+import android.app.ListActivity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+/**
+ * The launchpad activity for this sample project. This activity launches other activities that
+ * demonstrate implementations of common animations.
+ */
+public class MainActivity extends ListActivity {
+ /**
+ * This class describes an individual sample (the sample title, and the activity class that
+ * demonstrates this sample).
+ */
+ private class Sample {
+ private CharSequence title;
+ private Class<? extends Activity> activityClass;
+
+ public Sample(int titleResId, Class<? extends Activity> activityClass) {
+ this.activityClass = activityClass;
+ this.title = getResources().getString(titleResId);
+ }
+
+ @Override
+ public String toString() {
+ return title.toString();
+ }
+ }
+
+ /**
+ * The collection of all samples in the app. This gets instantiated in {@link
+ * #onCreate(android.os.Bundle)} because the {@link Sample} constructor needs access to {@link
+ * android.content.res.Resources}.
+ */
+ private static Sample[] mSamples;
+
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ // Instantiate the list of samples.
+ mSamples = new Sample[]{
+ new Sample(R.string.title_crossfade, CrossfadeActivity.class),
+ new Sample(R.string.title_card_flip, CardFlipActivity.class),
+ new Sample(R.string.title_screen_slide, ScreenSlideActivity.class),
+ new Sample(R.string.title_zoom, ZoomActivity.class),
+ new Sample(R.string.title_layout_changes, LayoutChangesActivity.class),
+ };
+
+ setListAdapter(new ArrayAdapter<Sample>(this,
+ android.R.layout.simple_list_item_1,
+ android.R.id.text1,
+ mSamples));
+ }
+
+ @Override
+ protected void onListItemClick(ListView listView, View view, int position, long id) {
+ // Launch the sample associated with this list position.
+ startActivity(new Intent(MainActivity.this, mSamples[position].activityClass));
+ }
+}
diff --git a/samples/training/AnimationsDemo/src/com/example/android/animationsdemo/ScreenSlideActivity.java b/samples/training/AnimationsDemo/src/com/example/android/animationsdemo/ScreenSlideActivity.java
new file mode 100644
index 000000000..4652a0ed8
--- /dev/null
+++ b/samples/training/AnimationsDemo/src/com/example/android/animationsdemo/ScreenSlideActivity.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.animationsdemo;
+
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v13.app.FragmentStatePagerAdapter;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.NavUtils;
+import android.support.v4.view.PagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.view.Menu;
+import android.view.MenuItem;
+
+/**
+ * Demonstrates a "screen-slide" animation using a {@link ViewPager}. Because {@link ViewPager}
+ * automatically plays such an animation when calling {@link ViewPager#setCurrentItem(int)}, there
+ * isn't any animation-specific code in this sample.
+ *
+ * <p>This sample shows a "next" button that advances the user to the next step in a wizard,
+ * animating the current screen out (to the left) and the next screen in (from the right). The
+ * reverse animation is played when the user presses the "previous" button.</p>
+ *
+ * @see ScreenSlidePageFragment
+ */
+public class ScreenSlideActivity 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);
+
+ // Instantiate a ViewPager and a PagerAdapter.
+ mPager = (ViewPager) findViewById(R.id.pager);
+ mPagerAdapter = new ScreenSlidePagerAdapter(getFragmentManager());
+ mPager.setAdapter(mPagerAdapter);
+ mPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
+ @Override
+ public void onPageSelected(int position) {
+ // When changing pages, reset the action bar actions since they are dependent
+ // on which page is currently active. An alternative approach is to have each
+ // fragment expose actions itself (rather than the activity exposing actions),
+ // but for simplicity, the activity provides the actions in this sample.
+ invalidateOptionsMenu();
+ }
+ });
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ getMenuInflater().inflate(R.menu.activity_screen_slide, menu);
+
+ menu.findItem(R.id.action_previous).setEnabled(mPager.getCurrentItem() > 0);
+
+ // Add either a "next" or "finish" button to the action bar, depending on which page
+ // is currently selected.
+ MenuItem item = menu.add(Menu.NONE, R.id.action_next, Menu.NONE,
+ (mPager.getCurrentItem() == mPagerAdapter.getCount() - 1)
+ ? R.string.action_finish
+ : R.string.action_next);
+ item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ // Navigate "up" the demo structure to the launchpad activity.
+ // See http://developer.android.com/design/patterns/navigation.html for more.
+ NavUtils.navigateUpTo(this, new Intent(this, MainActivity.class));
+ return true;
+
+ case R.id.action_previous:
+ // Go to the previous step in the wizard. If there is no previous step,
+ // setCurrentItem will do nothing.
+ mPager.setCurrentItem(mPager.getCurrentItem() - 1);
+ return true;
+
+ case R.id.action_next:
+ // Advance to the next step in the wizard. If there is no next step, setCurrentItem
+ // will do nothing.
+ mPager.setCurrentItem(mPager.getCurrentItem() + 1);
+ return true;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ /**
+ * A simple pager adapter that represents 5 {@link ScreenSlidePageFragment} objects, in
+ * sequence.
+ */
+ private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
+ public ScreenSlidePagerAdapter(FragmentManager fm) {
+ super(fm);
+ }
+
+ @Override
+ public Fragment getItem(int position) {
+ return ScreenSlidePageFragment.create(position);
+ }
+
+ @Override
+ public int getCount() {
+ return NUM_PAGES;
+ }
+ }
+}
diff --git a/samples/training/AnimationsDemo/src/com/example/android/animationsdemo/ScreenSlidePageFragment.java b/samples/training/AnimationsDemo/src/com/example/android/animationsdemo/ScreenSlidePageFragment.java
new file mode 100644
index 000000000..887c926bd
--- /dev/null
+++ b/samples/training/AnimationsDemo/src/com/example/android/animationsdemo/ScreenSlidePageFragment.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.animationsdemo;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+/**
+ * A fragment representing a single step in a wizard. The fragment shows a dummy title indicating
+ * the page number, along with some dummy text.
+ *
+ * <p>This class is used by the {@link CardFlipActivity} and {@link
+ * ScreenSlideActivity} samples.</p>
+ */
+public class ScreenSlidePageFragment extends Fragment {
+ /**
+ * The argument key for the page number this fragment represents.
+ */
+ public static final String ARG_PAGE = "page";
+
+ /**
+ * The fragment's page number, which is set to the argument value for {@link #ARG_PAGE}.
+ */
+ private int mPageNumber;
+
+ /**
+ * Factory method for this fragment class. Constructs a new fragment for the given page number.
+ */
+ public static ScreenSlidePageFragment create(int pageNumber) {
+ ScreenSlidePageFragment fragment = new ScreenSlidePageFragment();
+ Bundle args = new Bundle();
+ args.putInt(ARG_PAGE, pageNumber);
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ public ScreenSlidePageFragment() {
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mPageNumber = getArguments().getInt(ARG_PAGE);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ // Inflate the layout containing a title and body text.
+ ViewGroup rootView = (ViewGroup) inflater
+ .inflate(R.layout.fragment_screen_slide_page, container, false);
+
+ // Set the title view to show the page number.
+ ((TextView) rootView.findViewById(android.R.id.text1)).setText(
+ getString(R.string.title_template_step, mPageNumber + 1));
+
+ return rootView;
+ }
+
+ /**
+ * Returns the page number represented by this fragment object.
+ */
+ public int getPageNumber() {
+ return mPageNumber;
+ }
+}
diff --git a/samples/training/AnimationsDemo/src/com/example/android/animationsdemo/TouchHighlightImageButton.java b/samples/training/AnimationsDemo/src/com/example/android/animationsdemo/TouchHighlightImageButton.java
new file mode 100644
index 000000000..8fc3e0193
--- /dev/null
+++ b/samples/training/AnimationsDemo/src/com/example/android/animationsdemo/TouchHighlightImageButton.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.animationsdemo;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.widget.ImageButton;
+
+/**
+ * An image button that uses a blue highlight (@link android.R.attr.selectableItemBackground} to
+ * indicate pressed and focused states.
+ */
+public class TouchHighlightImageButton extends ImageButton {
+ /**
+ * The highlight drawable. This generally a {@link android.graphics.drawable.StateListDrawable}
+ * that's transparent in the default state, and contains a semi-transparent overlay
+ * for the focused and pressed states.
+ */
+ private Drawable mForegroundDrawable;
+
+ /**
+ * The cached bounds of the view.
+ */
+ private Rect mCachedBounds = new Rect();
+
+ public TouchHighlightImageButton(Context context) {
+ super(context);
+ init();
+ }
+
+ public TouchHighlightImageButton(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ public TouchHighlightImageButton(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init();
+ }
+
+ /**
+ * General view initialization used common to all constructors of the view.
+ */
+ private void init() {
+ // Reset default ImageButton background and padding.
+ setBackgroundColor(0);
+ setPadding(0, 0, 0, 0);
+
+ // Retrieve the drawable resource assigned to the android.R.attr.selectableItemBackground
+ // theme attribute from the current theme.
+ TypedArray a = getContext()
+ .obtainStyledAttributes(new int[]{android.R.attr.selectableItemBackground});
+ mForegroundDrawable = a.getDrawable(0);
+ mForegroundDrawable.setCallback(this);
+ a.recycle();
+ }
+
+ @Override
+ protected void drawableStateChanged() {
+ super.drawableStateChanged();
+
+ // Update the state of the highlight drawable to match
+ // the state of the button.
+ if (mForegroundDrawable.isStateful()) {
+ mForegroundDrawable.setState(getDrawableState());
+ }
+
+ // Trigger a redraw.
+ invalidate();
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ // First draw the image.
+ super.onDraw(canvas);
+
+ // Then draw the highlight on top of it. If the button is neither focused
+ // nor pressed, the drawable will be transparent, so just the image
+ // will be drawn.
+ mForegroundDrawable.setBounds(mCachedBounds);
+ mForegroundDrawable.draw(canvas);
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+
+ // Cache the view bounds.
+ mCachedBounds.set(0, 0, w, h);
+ }
+}
diff --git a/samples/training/AnimationsDemo/src/com/example/android/animationsdemo/ZoomActivity.java b/samples/training/AnimationsDemo/src/com/example/android/animationsdemo/ZoomActivity.java
new file mode 100644
index 000000000..70dcfcbd5
--- /dev/null
+++ b/samples/training/AnimationsDemo/src/com/example/android/animationsdemo/ZoomActivity.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.animationsdemo;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.content.Intent;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.NavUtils;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.animation.DecelerateInterpolator;
+import android.widget.ImageView;
+
+/**
+ * A sample showing how to zoom an image thumbnail to full-screen, by animating the bounds of the
+ * zoomed image from the thumbnail bounds to the screen bounds.
+ *
+ * <p>In this sample, the user can touch one of two images. Touching an image zooms it in, covering
+ * the entire activity content area. Touching the zoomed-in image hides it.</p>
+ */
+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);
+ }
+ });
+
+ final View thumb2View = findViewById(R.id.thumb_button_2);
+ thumb2View.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ zoomImageFromThumb(thumb2View, R.drawable.image2);
+ }
+ });
+
+ // Retrieve and cache the system's default "short" animation time.
+ mShortAnimationDuration = getResources().getInteger(android.R.integer.config_shortAnimTime);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ // Navigate "up" the demo structure to the launchpad activity.
+ // See http://developer.android.com/design/patterns/navigation.html for more.
+ NavUtils.navigateUpTo(this, new Intent(this, MainActivity.class));
+ return true;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ /**
+ * "Zooms" in a thumbnail view by assigning the high resolution image to a hidden "zoomed-in"
+ * image view and animating its bounds to fit the entire activity content area. More
+ * specifically:
+ *
+ * <ol>
+ * <li>Assign the high-res image to the hidden "zoomed-in" (expanded) image view.</li>
+ * <li>Calculate the starting and ending bounds for the expanded view.</li>
+ * <li>Animate each of four positioning/sizing properties (X, Y, SCALE_X, SCALE_Y)
+ * simultaneously, from the starting bounds to the ending bounds.</li>
+ * <li>Zoom back out by running the reverse animation on click.</li>
+ * </ol>
+ *
+ * @param thumbView The thumbnail view to zoom in.
+ * @param imageResId The high-resolution version of the image represented by the thumbnail.
+ */
+ 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;
+ }
+ });
+ }
+}