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