1 package com.example.android.apis.animation;
2 
3 import com.example.android.apis.R;
4 
5 import android.app.Activity;
6 import android.os.Bundle;
7 import android.widget.ListView;
8 import android.widget.ArrayAdapter;
9 import android.widget.AdapterView;
10 import android.widget.ImageView;
11 import android.view.View;
12 import android.view.ViewGroup;
13 import android.view.animation.Animation;
14 import android.view.animation.AccelerateInterpolator;
15 import android.view.animation.DecelerateInterpolator;
16 
17 /**
18  * This sample application shows how to use layout animation and various
19  * transformations on views. The result is a 3D transition between a
20  * ListView and an ImageView. When the user clicks the list, it flips to
21  * show the picture. When the user clicks the picture, it flips to show the
22  * list. The animation is made of two smaller animations: the first half
23  * rotates the list by 90 degrees on the Y axis and the second half rotates
24  * the picture by 90 degrees on the Y axis. When the first half finishes, the
25  * list is made invisible and the picture is set visible.
26  */
27 public class Transition3d extends Activity implements
28         AdapterView.OnItemClickListener, View.OnClickListener {
29     private ListView mPhotosList;
30     private ViewGroup mContainer;
31     private ImageView mImageView;
32 
33     // Names of the photos we show in the list
34     private static final String[] PHOTOS_NAMES = new String[] {
35             "Lyon",
36             "Livermore",
37             "Tahoe Pier",
38             "Lake Tahoe",
39             "Grand Canyon",
40             "Bodie"
41     };
42 
43     // Resource identifiers for the photos we want to display
44     private static final int[] PHOTOS_RESOURCES = new int[] {
45             R.drawable.photo1,
46             R.drawable.photo2,
47             R.drawable.photo3,
48             R.drawable.photo4,
49             R.drawable.photo5,
50             R.drawable.photo6
51     };
52 
53     @Override
onCreate(Bundle savedInstanceState)54     protected void onCreate(Bundle savedInstanceState) {
55         super.onCreate(savedInstanceState);
56 
57         setContentView(R.layout.animations_main_screen);
58 
59         mPhotosList = (ListView) findViewById(android.R.id.list);
60         mImageView = (ImageView) findViewById(R.id.picture);
61         mContainer = (ViewGroup) findViewById(R.id.container);
62 
63         // Prepare the ListView
64         final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
65                 android.R.layout.simple_list_item_1, PHOTOS_NAMES);
66 
67         mPhotosList.setAdapter(adapter);
68         mPhotosList.setOnItemClickListener(this);
69 
70         // Prepare the ImageView
71         mImageView.setClickable(true);
72         mImageView.setFocusable(true);
73         mImageView.setOnClickListener(this);
74 
75         // Since we are caching large views, we want to keep their cache
76         // between each animation
77         mContainer.setPersistentDrawingCache(ViewGroup.PERSISTENT_ANIMATION_CACHE);
78     }
79 
80     /**
81      * Setup a new 3D rotation on the container view.
82      *
83      * @param position the item that was clicked to show a picture, or -1 to show the list
84      * @param start the start angle at which the rotation must begin
85      * @param end the end angle of the rotation
86      */
applyRotation(int position, float start, float end)87     private void applyRotation(int position, float start, float end) {
88         // Find the center of the container
89         final float centerX = mContainer.getWidth() / 2.0f;
90         final float centerY = mContainer.getHeight() / 2.0f;
91 
92         // Create a new 3D rotation with the supplied parameter
93         // The animation listener is used to trigger the next animation
94         final Rotate3dAnimation rotation =
95                 new Rotate3dAnimation(start, end, centerX, centerY, 310.0f, true);
96         rotation.setDuration(500);
97         rotation.setFillAfter(true);
98         rotation.setInterpolator(new AccelerateInterpolator());
99         rotation.setAnimationListener(new DisplayNextView(position));
100 
101         mContainer.startAnimation(rotation);
102     }
103 
onItemClick(AdapterView<?> parent, View v, int position, long id)104     public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
105         // Pre-load the image then start the animation
106         mImageView.setImageResource(PHOTOS_RESOURCES[position]);
107         applyRotation(position, 0, 90);
108     }
109 
onClick(View v)110     public void onClick(View v) {
111         applyRotation(-1, 180, 90);
112     }
113 
114     /**
115      * This class listens for the end of the first half of the animation.
116      * It then posts a new action that effectively swaps the views when the container
117      * is rotated 90 degrees and thus invisible.
118      */
119     private final class DisplayNextView implements Animation.AnimationListener {
120         private final int mPosition;
121 
DisplayNextView(int position)122         private DisplayNextView(int position) {
123             mPosition = position;
124         }
125 
onAnimationStart(Animation animation)126         public void onAnimationStart(Animation animation) {
127         }
128 
onAnimationEnd(Animation animation)129         public void onAnimationEnd(Animation animation) {
130             mContainer.post(new SwapViews(mPosition));
131         }
132 
onAnimationRepeat(Animation animation)133         public void onAnimationRepeat(Animation animation) {
134         }
135     }
136 
137     /**
138      * This class is responsible for swapping the views and start the second
139      * half of the animation.
140      */
141     private final class SwapViews implements Runnable {
142         private final int mPosition;
143 
SwapViews(int position)144         public SwapViews(int position) {
145             mPosition = position;
146         }
147 
run()148         public void run() {
149             final float centerX = mContainer.getWidth() / 2.0f;
150             final float centerY = mContainer.getHeight() / 2.0f;
151             Rotate3dAnimation rotation;
152 
153             if (mPosition > -1) {
154                 mPhotosList.setVisibility(View.GONE);
155                 mImageView.setVisibility(View.VISIBLE);
156                 mImageView.requestFocus();
157 
158                 rotation = new Rotate3dAnimation(90, 180, centerX, centerY, 310.0f, false);
159             } else {
160                 mImageView.setVisibility(View.GONE);
161                 mPhotosList.setVisibility(View.VISIBLE);
162                 mPhotosList.requestFocus();
163 
164                 rotation = new Rotate3dAnimation(90, 0, centerX, centerY, 310.0f, false);
165             }
166 
167             rotation.setDuration(500);
168             rotation.setFillAfter(true);
169             rotation.setInterpolator(new DecelerateInterpolator());
170 
171             mContainer.startAnimation(rotation);
172         }
173     }
174 
175 }
176