Android中的翻转动画效果的实现,首先看一下运行效果如上图所示.
Android中并没有提供直接做3D翻转的动画,所以关于3D翻转的动画效果需要我们自己实现,那么我们首先来分析一下Animation 和 Transformation。
Animation动画的主要接口,其中主要定义了动画的一些属性比如开始时间,持续时间,是否重复播放等等。而Transformation中则包含一个矩阵和alpha值,矩阵是用来做平移,旋转和缩放动画的,而alpha值是用来做alpha动画的,要实现3D旋转动画我们需要继承自Animation类来实现,我们需要重载getTransformation和applyTransformation,在getTransformation中Animation会根据动画的属性来产生一系列的差值点,然后将这些差值点传给applyTransformation,这个函数将根据这些点来生成不同的Transformation。下面是具体实现:
1 package com.example.textviewtest; 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 public class Rotate3dAnimation extends Animation { 9 // 开始角度 10 private final float mFromDegrees; 11 // 结束角度 12 private final float mToDegrees; 13 // 中心点 14 private final float mCenterX; 15 private final float mCenterY; 16 private final float mDepthZ; 17 // 是否需要扭曲 18 private final boolean mReverse; 19 // 摄像头 20 private Camera mCamera; 21 22 public Rotate3dAnimation(float fromDegrees, float toDegrees, float centerX, 23 float centerY, float depthZ, boolean reverse) { 24 mFromDegrees = fromDegrees; 25 mToDegrees = toDegrees; 26 mCenterX = centerX; 27 mCenterY = centerY; 28 mDepthZ = depthZ; 29 mReverse = reverse; 30 } 31 32 @Override 33 public void initialize(int width, int height, int parentWidth, 34 int parentHeight) { 35 super.initialize(width, height, parentWidth, parentHeight); 36 mCamera = new Camera(); 37 } 38 39 // 生成Transformation 40 @Override 41 protected void applyTransformation(float interpolatedTime, Transformation t) { 42 final float fromDegrees = mFromDegrees; 43 // 生成中间角度 44 float degrees = fromDegrees 45 + ((mToDegrees - fromDegrees) * interpolatedTime); 46 47 final float centerX = mCenterX; 48 final float centerY = mCenterY; 49 final Camera camera = mCamera; 50 51 final Matrix matrix = t.getMatrix(); 52 53 camera.save(); 54 if (mReverse) { 55 camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime); 56 } else { 57 camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime)); 58 } 59 camera.rotateY(degrees); 60 // 取得变换后的矩阵 61 camera.getMatrix(matrix); 62 camera.restore(); 63 64 matrix.preTranslate(-centerX, -centerY); 65 matrix.postTranslate(centerX, centerY); 66 } 67 }
其中包括了旋转的开始和结束角度,中心点、是否扭曲、和一个Camera,这里我们主要分析applyTransformation函数,其中第一个参数就是通过getTransformation函数传递的差指点,然后我们根据这个差值通过线性差值算法计算出一个中间角度degrees,Camera类是用来实现绕Y轴旋转后透视投影的,因此我们首先通过t.getMatrix()取得当前的矩阵,然后通过camera.translate来对矩阵进行平移变换操作,camera.rotateY进行旋转。这样我们就可以很轻松的实现3D旋转效果了。
下面是布局文件main.xml:
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:background="@drawable/main_screen_bg" 6 android:gravity="center_horizontal" 7 android:orientation="vertical" 8 tools:context=".MainActivity" > 9 10 <Button 11 android:id="@+id/next_btn" 12 android:layout_width="wrap_content" 13 android:layout_height="wrap_content" 14 android:layout_marginTop="20dip" 15 android:drawableTop="@drawable/qiangpiao_dropdown" 16 android:text="下一个" /> 17 18 <TextView 19 android:id="@+id/tv" 20 android:layout_width="300dip" 21 android:layout_height="300dip" 22 android:layout_gravity="center" 23 android:background="@drawable/call_show_frame_safe" 24 android:gravity="center" 25 android:textColor="#ffffff" 26 android:textSize="15sp" /> 27 28 </LinearLayout>
MainActivity的代码如下:
1 package com.example.textviewtest; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.view.Menu; 6 import android.view.View; 7 import android.view.animation.AccelerateInterpolator; 8 import android.view.animation.Animation; 9 import android.view.animation.DecelerateInterpolator; 10 import android.widget.Button; 11 import android.widget.TextView; 12 13 public class MainActivity extends Activity { 14 private TextView tv; 15 private Button btn; 16 private int count = 1; 17 18 @Override 19 protected void onCreate(Bundle savedInstanceState) { 20 super.onCreate(savedInstanceState); 21 setContentView(R.layout.activity_main); 22 tv = (TextView) findViewById(R.id.tv); 23 tv.setText(String.valueOf(count)); 24 btn = (Button) findViewById(R.id.next_btn); 25 applyRotation(0, 90); 26 27 btn.setOnClickListener(new View.OnClickListener() { 28 29 @Override 30 public void onClick(View v) { 31 applyRotation(0, 90); 32 } 33 }); 34 35 } 36 37 private void applyRotation(float start, float end) { 38 // 计算中心点 39 final float centerX = tv.getWidth() / 2.0f; 40 final float centerY = tv.getHeight() / 2.0f; 41 42 final Rotate3dAnimation rotation = new Rotate3dAnimation(start, end, 43 centerX, centerY, 310.0f, true); 44 rotation.setDuration(500); 45 rotation.setFillAfter(true); 46 rotation.setInterpolator(new AccelerateInterpolator()); 47 // 设置监听 48 rotation.setAnimationListener(new DisplayNextView()); 49 50 tv.startAnimation(rotation); 51 } 52 53 private final class DisplayNextView implements Animation.AnimationListener { 54 55 public void onAnimationStart(Animation animation) { 56 } 57 58 // 动画结束 59 public void onAnimationEnd(Animation animation) { 60 tv.post(new SwapViews()); 61 } 62 63 public void onAnimationRepeat(Animation animation) { 64 } 65 } 66 67 private final class SwapViews implements Runnable { 68 69 public void run() { 70 final float centerX = tv.getWidth() / 2.0f; 71 final float centerY = tv.getHeight() / 2.0f; 72 Rotate3dAnimation rotation = null; 73 74 tv.requestFocus(); 75 76 rotation = new Rotate3dAnimation(90, 0, centerX, centerY, 310.0f, 77 false); 78 rotation.setDuration(500); 79 rotation.setFillAfter(true); 80 rotation.setInterpolator(new DecelerateInterpolator()); 81 // 开始动画 82 tv.startAnimation(rotation); 83 tv.setText(String.valueOf(count++)); 84 } 85 } 86 87 @Override 88 public boolean onCreateOptionsMenu(Menu menu) { 89 getMenuInflater().inflate(R.menu.activity_main, menu); 90 return true; 91 } 92 93 }
看懂了吗?呵呵。