Android 3D旋转动画效果

转载+源码实现:
源码下载:http://download.csdn.net/detail/heng615975867/6521879
这篇文章主要介绍一下如何实现View的3D旋转效果,实现的主要原理就是围绕Y轴旋转,同时在Z轴方面上有一个深入的缩放。

演示的demo主要有以下几个重点:

1,自定义旋转动画

2,动画做完后,重置ImageView


先看一下程序的运行效果:

Android 3D旋转动画效果_第1张图片

1,自定义动画类


这里实现了一个Rotate3dAnimation的类,它扩展了Animation类,重写applyTransformation()方法,提供指定时间的矩阵变换,我们在这个方法里,就可以利用Camera类得得到一个围绕Y轴旋转的matrix,把这个matrix设置到Transformation对象中。  具体的实现代码如下:

[java]  view plain copy
  1. @Override  
  2. protected void applyTransformation(float interpolatedTime, Transformation t)  
  3. {  
  4.         final float fromDegrees = mFromDegrees;  
  5.         float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);  
  6.   
  7.         final float centerX = mCenterX;  
  8.         final float centerY = mCenterY;  
  9.         final Camera camera = mCamera;  
  10.   
  11.         final Matrix matrix = t.getMatrix();  
  12.   
  13.         camera.save();  
  14.         if (mReverse) {  
  15.             camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);  
  16.         } else {  
  17.             camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));  
  18.         }  
  19.         camera.rotateY(degrees);  
  20.         camera.getMatrix(matrix);  
  21.         camera.restore();  
  22.   
  23.         matrix.preTranslate(-centerX, -centerY);  
  24.         matrix.postTranslate(centerX, centerY);  
  25. }  

2,如何使用这个动画类


在Activity中,我们有两个大小一样的ImageView,它们都放在FrameLayout中,这样他们位置是重叠的,对最上面的ImageView做动画(旋转角度从0到90),当动画做完后,再对后面的ImageView做动画(旋转角度从90到180),在这里,要控制相应的ImageView隐藏或显示。

动画的listener实现如下: 


[java]  view plain copy
  1. private final class DisplayNextView implements Animation.AnimationListener {  
  2.   
  3.         public void onAnimationStart(Animation animation) {  
  4.         }  
  5.   
  6.         public void onAnimationEnd(Animation animation) {  
  7.   
  8.             mContainer.post(new SwapViews());  
  9.         }  
  10.   
  11.         public void onAnimationRepeat(Animation animation) {  
  12.         }  
  13.     }  

动画做完后,执行的代码如下:


[java]  view plain copy
  1. private final class SwapViews implements Runnable  
  2.     {  
  3.         @Override  
  4.         public void run()  
  5.         {  
  6.             mImageView1.setVisibility(View.GONE);  
  7.             mImageView2.setVisibility(View.GONE);  
  8.   
  9.             mIndex++;  
  10.             if (0 == mIndex % 2)  
  11.             {  
  12.                 mStartAnimView = mImageView1;  
  13.             }  
  14.             else  
  15.             {  
  16.                 mStartAnimView = mImageView2;  
  17.             }  
  18.   
  19.             mStartAnimView.setVisibility(View.VISIBLE);  
  20.             mStartAnimView.requestFocus();  
  21.   
  22.             Rotate3dAnimation rotation = new Rotate3dAnimation(  
  23.                     -90,  
  24.                     0,  
  25.                     mCenterX,  
  26.                     mCenterY, mDepthZ, false);  
  27.   
  28.             rotation.setDuration(mDuration);  
  29.             rotation.setFillAfter(true);  
  30.             rotation.setInterpolator(new DecelerateInterpolator());  
  31.             mStartAnimView.startAnimation(rotation);  
  32.         }  
  33.     }  

点击Button的事件处理实现:


[java]  view plain copy
  1. @Override  
  2. public void onClick(View v)  
  3. {  
  4.     mCenterX = mContainer.getWidth() / 2;  
  5.     mCenterY = mContainer.getHeight() / 2;  
  6.   
  7.     getDepthZ();  
  8.   
  9.     applyRotation(mStartAnimView, 090);  
  10. }  

applyRotation的实现如下:


[java]  view plain copy
  1. private void applyRotation(View animView, float startAngle, float toAngle)  
  2.     {  
  3.         float centerX = mCenterX;  
  4.         float centerY = mCenterY;  
  5.         Rotate3dAnimation rotation = new Rotate3dAnimation(  
  6.                 startAngle, toAngle, centerX, centerY, mDepthZ, true);  
  7.         rotation.setDuration(mDuration);  
  8.         rotation.setFillAfter(true);  
  9.         rotation.setInterpolator(new AccelerateInterpolator());  
  10.         rotation.setAnimationListener(new DisplayNextView());  
  11.   
  12.         animView.startAnimation(rotation);  
  13.     }  


3,完整代码如下


Rotate3dAnimActivity.java


[java]  view plain copy
  1. public class Rotate3dAnimActivity extends Activity  
  2. {  
  3.     ImageView mImageView1 = null;  
  4.     ImageView mImageView2 = null;  
  5.     ImageView mStartAnimView = null;  
  6.     View mContainer = null;  
  7.     int mDuration = 500;  
  8.     float mCenterX = 0.0f;  
  9.     float mCenterY = 0.0f;  
  10.     float mDepthZ  = 0.0f;  
  11.     int mIndex = 0;  
  12.       
  13.     @Override  
  14.     public void onCreate(Bundle savedInstanceState)  
  15.     {  
  16.         super.onCreate(savedInstanceState);  
  17.           
  18.         setContentView(R.layout.rotate_anim);  
  19.           
  20.         mImageView1 = (ImageView) findViewById(R.id.imageView1);  
  21.         mImageView2 = (ImageView) findViewById(R.id.imageView2);  
  22.         mContainer  = findViewById(R.id.container);  
  23.         mStartAnimView = mImageView1;  
  24.           
  25.         findViewById(R.id.button1).setOnClickListener(new View.OnClickListener()  
  26.         {  
  27.             @Override  
  28.             public void onClick(View v)  
  29.             {  
  30.                 mCenterX = mContainer.getWidth() / 2;  
  31.                 mCenterY = mContainer.getHeight() / 2;  
  32.                   
  33.                 getDepthZ();  
  34.                   
  35.                 applyRotation(mStartAnimView, 090);  
  36.             }  
  37.         });  
  38.           
  39.         InputMethodManager imm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);  
  40.         imm.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);  
  41.     }  
  42.       
  43.     private void getDepthZ()  
  44.     {  
  45.         EditText editText = (EditText) findViewById(R.id.edit_depthz);  
  46.         String string = editText.getText().toString();  
  47.           
  48.         try  
  49.         {  
  50.             mDepthZ = (float)Integer.parseInt(string);  
  51.             //mDepthZ = Math.min(mDepthZ, 300.0f);  
  52.         }  
  53.         catch (Exception e)  
  54.         {  
  55.             e.printStackTrace();  
  56.         }  
  57.     }  
  58.       
  59.     private void applyRotation(View animView, float startAngle, float toAngle)  
  60.     {  
  61.         float centerX = mCenterX;  
  62.         float centerY = mCenterY;  
  63.         Rotate3dAnimation rotation = new Rotate3dAnimation(  
  64.                 startAngle, toAngle, centerX, centerY, mDepthZ, true);  
  65.         rotation.setDuration(mDuration);  
  66.         rotation.setFillAfter(true);  
  67.         rotation.setInterpolator(new AccelerateInterpolator());  
  68.         rotation.setAnimationListener(new DisplayNextView());  
  69.           
  70.         animView.startAnimation(rotation);  
  71.     }  
  72.       
  73.     /** 
  74.      * This class listens for the end of the first half of the animation. 
  75.      * It then posts a new action that effectively swaps the views when the container 
  76.      * is rotated 90 degrees and thus invisible. 
  77.      */  
  78.     private final class DisplayNextView implements Animation.AnimationListener {  
  79.   
  80.         public void onAnimationStart(Animation animation) {  
  81.         }  
  82.   
  83.         public void onAnimationEnd(Animation animation) {  
  84.               
  85.             mContainer.post(new SwapViews());  
  86.         }  
  87.   
  88.         public void onAnimationRepeat(Animation animation) {  
  89.         }  
  90.     }  
  91.       
  92.     private final class SwapViews implements Runnable  
  93.     {  
  94.         @Override  
  95.         public void run()  
  96.         {  
  97.             mImageView1.setVisibility(View.GONE);  
  98.             mImageView2.setVisibility(View.GONE);  
  99.               
  100.             mIndex++;  
  101.             if (0 == mIndex % 2)  
  102.             {  
  103.                 mStartAnimView = mImageView1;  
  104.             }  
  105.             else  
  106.             {  
  107.                 mStartAnimView = mImageView2;  
  108.             }  
  109.               
  110.             mStartAnimView.setVisibility(View.VISIBLE);  
  111.             mStartAnimView.requestFocus();  
  112.               
  113.             Rotate3dAnimation rotation = new Rotate3dAnimation(  
  114.                     -90,   
  115.                     0,   
  116.                     mCenterX,  
  117.                     mCenterY, mDepthZ, false);  
  118.               
  119.             rotation.setDuration(mDuration);  
  120.             rotation.setFillAfter(true);  
  121.             rotation.setInterpolator(new DecelerateInterpolator());  
  122.             mStartAnimView.startAnimation(rotation);  
  123.         }  
  124.     }  
  125. }  

rotate_anim.xml

[html]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical" >  
  6.   
  7.     <Button  
  8.         android:id="@+id/button1"  
  9.         android:layout_width="wrap_content"  
  10.         android:layout_height="wrap_content"  
  11.         android:layout_margin="20dp"  
  12.         android:text="Do 3d animation" />  
  13.       
  14.     <TextView   
  15.         android:layout_width="wrap_content"  
  16.         android:layout_height="wrap_content"  
  17.         android:layout_marginLeft="20px"  
  18.         android:text="Input Depth on Z axis. [0, 300]"  
  19.         />  
  20.     <EditText   
  21.         android:id="@+id/edit_depthz"  
  22.         android:layout_width="200dp"  
  23.         android:layout_height="wrap_content"  
  24.         android:layout_margin="20dp"  
  25.         android:text="0"/>  
  26.   
  27.     <FrameLayout   
  28.         android:id="@+id/container"  
  29.         android:layout_width="wrap_content"  
  30.         android:layout_height="wrap_content">  
  31.        <ImageView  
  32.         android:id="@+id/imageView1"  
  33.         android:layout_width="200dp"  
  34.         android:layout_height="200dp"  
  35.         android:layout_margin="20dp"  
  36.         android:src="@drawable/f" />  
  37.          
  38.        <ImageView  
  39.         android:id="@+id/imageView2"  
  40.         android:layout_width="200dp"  
  41.         android:layout_height="200dp"  
  42.         android:layout_margin="20dp"  
  43.         android:src="@drawable/s"   
  44.         android:visibility="gone"/>  
  45.           
  46.     </FrameLayout>  
  47.   
  48. </LinearLayout>  


Rotate3dAnimation.java


[java]  view plain copy
  1. package com.nj1s.lib.anim;  
  2.   
  3. import android.graphics.Camera;  
  4. import android.graphics.Matrix;  
  5. import android.view.animation.Animation;  
  6. import android.view.animation.Transformation;  
  7.   
  8. /** 
  9.  * An animation that rotates the view on the Y axis between two specified angles. 
  10.  * This animation also adds a translation on the Z axis (depth) to improve the effect. 
  11.  */  
  12. public class Rotate3dAnimation extends Animation {  
  13.     private final float mFromDegrees;  
  14.     private final float mToDegrees;  
  15.     private final float mCenterX;  
  16.     private final float mCenterY;  
  17.     private final float mDepthZ;  
  18.     private final boolean mReverse;  
  19.     private Camera mCamera;  
  20.   
  21.     /** 
  22.      * Creates a new 3D rotation on the Y axis. The rotation is defined by its 
  23.      * start angle and its end angle. Both angles are in degrees. The rotation 
  24.      * is performed around a center point on the 2D space, definied by a pair 
  25.      * of X and Y coordinates, called centerX and centerY. When the animation 
  26.      * starts, a translation on the Z axis (depth) is performed. The length 
  27.      * of the translation can be specified, as well as whether the translation 
  28.      * should be reversed in time. 
  29.      * 
  30.      * @param fromDegrees the start angle of the 3D rotation 
  31.      * @param toDegrees the end angle of the 3D rotation 
  32.      * @param centerX the X center of the 3D rotation 
  33.      * @param centerY the Y center of the 3D rotation 
  34.      * @param reverse true if the translation should be reversed, false otherwise 
  35.      */  
  36.     public Rotate3dAnimation(float fromDegrees, float toDegrees,  
  37.             float centerX, float centerY, float depthZ, boolean reverse) {  
  38.         mFromDegrees = fromDegrees;  
  39.         mToDegrees = toDegrees;  
  40.         mCenterX = centerX;  
  41.         mCenterY = centerY;  
  42.         mDepthZ = depthZ;  
  43.         mReverse = reverse;  
  44.     }  
  45.   
  46.     @Override  
  47.     public void initialize(int width, int height, int parentWidth, int parentHeight) {  
  48.         super.initialize(width, height, parentWidth, parentHeight);  
  49.         mCamera = new Camera();  
  50.     }  
  51.   
  52.     @Override  
  53.     protected void applyTransformation(float interpolatedTime, Transformation t) {  
  54.         final float fromDegrees = mFromDegrees;  
  55.         float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);  
  56.   
  57.         final float centerX = mCenterX;  
  58.         final float centerY = mCenterY;  
  59.         final Camera camera = mCamera;  
  60.   
  61.         final Matrix matrix = t.getMatrix();  
  62.   
  63.         camera.save();  
  64.         if (mReverse) {  
  65.             camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);  
  66.         } else {  
  67.             camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));  
  68.         }  
  69.         camera.rotateY(degrees);  
  70.         camera.getMatrix(matrix);  
  71.         camera.restore();  
  72.   
  73.         matrix.preTranslate(-centerX, -centerY);  
  74.         matrix.postTranslate(centerX, centerY);  
  75.     }  
  76. }  

各位,请想一想,为实现applyTransformation方法时,最后的为什么要有这两句话:

        matrix.preTranslate(-centerX, -centerY);
        matrix.postTranslate(centerX, centerY);

你可能感兴趣的:(Android 3D旋转动画效果)