看到很多人在问如何实现三维的翻转效果,所以今天在这里简单的给大家分析一下,其实在APIDemo中就有这样一个例子,那么我们就以其为例来学习Android中的翻转动画效果的实现,首先看一下运行效果如下图所示。

Android中并没有提供直接做3D翻转的动画,所以关于3D翻转的动画效果需要我们自己实现,那么我们首先来分析一下Animation 和 Transformation。

Animation动画的主要接口,其中主要定义了动画的一些属性比如开始时间,持续时间,是否重复播放等等。而Transformation中则包含一个矩阵和alpha值,矩阵是用来做平移,旋转和缩放动画的,而alpha值是用来做alpha动画的,要实现3D旋转动画我们需要继承自Animation类来实现,我们需要重载getTransformation和applyTransformation,在getTransformation中Animation会根据动画的属性来产生一系列的差值点,然后将这些差值点传给applyTransformation,这个函数将根据这些点来生成不同的Transformation。下面是具体实现:

        
  1. publicclassRotate3dAnimationextendsAnimation{
  2. //开始角度
  3. privatefinalfloatmFromDegrees;
  4. //结束角度
  5. privatefinalfloatmToDegrees;
  6. //中心点
  7. privatefinalfloatmCenterX;
  8. privatefinalfloatmCenterY;
  9. privatefinalfloatmDepthZ;
  10. //是否需要扭曲
  11. privatefinalbooleanmReverse;
  12. //摄像头
  13. privateCameramCamera;
  14. publicRotate3dAnimation(floatfromDegrees,floattoDegrees,
  15. floatcenterX,floatcenterY,floatdepthZ,booleanreverse){
  16. mFromDegrees=fromDegrees;
  17. mToDegrees=toDegrees;
  18. mCenterX=centerX;
  19. mCenterY=centerY;
  20. mDepthZ=depthZ;
  21. mReverse=reverse;
  22. }
  23. @Override
  24. publicvoidinitialize(intwidth,intheight,intparentWidth,intparentHeight){
  25. super.initialize(width,height,parentWidth,parentHeight);
  26. mCamera=newCamera();
  27. }
  28. //生成Transformation
  29. @Override
  30. protectedvoidapplyTransformation(floatinterpolatedTime,Transformationt){
  31. finalfloatfromDegrees=mFromDegrees;
  32. //生成中间角度
  33. floatdegrees=fromDegrees+((mToDegrees-fromDegrees)*interpolatedTime);
  34. finalfloatcenterX=mCenterX;
  35. finalfloatcenterY=mCenterY;
  36. finalCameracamera=mCamera;
  37. finalMatrixmatrix=t.getMatrix();
  38. camera.save();
  39. if(mReverse){
  40. camera.translate(0.0f,0.0f,mDepthZ*interpolatedTime);
  41. }else{
  42. camera.translate(0.0f,0.0f,mDepthZ*(1.0f-interpolatedTime));
  43. }
  44. camera.rotateY(degrees);
  45. //取得变换后的矩阵
  46. camera.getMatrix(matrix);
  47. camera.restore();
  48. matrix.preTranslate(-centerX,-centerY);
  49. matrix.postTranslate(centerX,centerY);
  50. }
  51. }

其中包括了旋转的开始和结束角度,中心点、是否扭曲、和一个Camera,这里我们主要分析applyTransformation函数,其中第一个参数就是通过getTransformation函数传递的差指点,然后我们根据这个差值通过线性差值算法计算出一个中间角度degrees,Camera类是用来实现绕Y轴旋转后透视投影的,因此我们首先通过t.getMatrix()取得当前的矩阵,然后通过camera.translate来对矩阵进行平移变换操作,camera.rotateY进行旋转。这样我们就可以很轻松的实现3D旋转效果了,该例子的原意是通过一个列表来供用户选择要实现翻转的图像,所以我们分析至少需要定义两个控件:ListView和ImageView(要翻转的图像),主界面的xml布局定义如下所示。

        
  1. <FrameLayoutxmlns:android="http://schemas.android.com/apk/res/android"
  2. android:id="@+id/container"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent">
  5. <ListView
  6. android:id="@android:id/list"
  7. android:persistentDrawingCache="animation|scrolling"
  8. android:layout_width="match_parent"
  9. android:layout_height="match_parent"
  10. android:layoutAnimation="@anim/layout_bottom_to_top_slide"/>
  11. <ImageView
  12. android:id="@+id/picture"
  13. android:scaleType="fitCenter"
  14. android:layout_width="match_parent"
  15. android:layout_height="match_parent"
  16. android:visibility="gone"/>
  17. </FrameLayout>

然后准备好需要的资源,在onCreate函数中准备好ListView和ImageView,因为要旋转所以我们需要保存视图的缓存信息,通过setPersistentDrawingCache(ViewGroup.PERSISTENT_ANIMATION_CACHE);可以设置该功能,当我们选择列表中的图像资源后在onItemClick中将选择的资源Id对应的图像设置到ImageView中,然后通过applyRotation来启动一个动画,前面有了Rotate3dAnimation的实现,我们要完成3D翻转动画就很简单,直接构建一个Rotate3dAnimation对象,设置其属性(包括动画监听),这里将动画的监听设置为DisplayNextView,可以用来显示下一个视图,在其中的动画结束监听(onAnimationEnd)中,通过一个县城SwapViews来交换两个画面,交换过程则是设置ImageView和ListView的显示相关属性,并构建一个Rotate3dAnimation对象,对另一个界面进行旋转即可,然后启动动画,整个转换过程实际上就是将第一个界面从0度转好90度,然后就爱你过第二个界面从90度转到0度,这样就形成了一个翻转动画,完整代码如下,我们也加入了一些必要的注解,大家也可以参考APIDemo中的Transition3d例子。

        
  1. publicclassTransition3dextendsActivityimplements
  2. AdapterView.OnItemClickListener,View.OnClickListener{
  3. //照片列表
  4. privateListViewmPhotosList;
  5. privateViewGroupmContainer;
  6. privateImageViewmImageView;
  7. //照片的名字,用于显示在list中
  8. privatestaticfinalString[]PHOTOS_NAMES=newString[]{
  9. "Lyon",
  10. "Livermore",
  11. "TahoePier",
  12. "LakeTahoe",
  13. "GrandCanyon",
  14. "Bodie"
  15. };
  16. //资源id
  17. privatestaticfinalint[]PHOTOS_RESOURCES=newint[]{
  18. R.drawable.photo1,
  19. R.drawable.photo2,
  20. R.drawable.photo3,
  21. R.drawable.photo4,
  22. R.drawable.photo5,
  23. R.drawable.photo6
  24. };
  25. @Override
  26. protectedvoidonCreate(BundlesavedInstanceState){
  27. super.onCreate(savedInstanceState);
  28. setContentView(R.layout.animations_main_screen);
  29. mPhotosList=(ListView)findViewById(android.R.id.list);
  30. mImageView=(ImageView)findViewById(R.id.picture);
  31. mContainer=(ViewGroup)findViewById(R.id.container);
  32. //准备ListView
  33. finalArrayAdapter<String>adapter=newArrayAdapter<String>(this,
  34. android.R.layout.simple_list_item_1,PHOTOS_NAMES);
  35. mPhotosList.setAdapter(adapter);
  36. mPhotosList.setOnItemClickListener(this);
  37. //准备ImageView
  38. mImageView.setClickable(true);
  39. mImageView.setFocusable(true);
  40. mImageView.setOnClickListener(this);
  41. //设置需要保存缓存
  42. mContainer.setPersistentDrawingCache(ViewGroup.PERSISTENT_ANIMATION_CACHE);
  43. }
  44. /**
  45. *Setupanew3Drotationonthecontainerview.
  46. *
  47. *@parampositiontheitemthatwasclickedtoshowapicture,or-1toshowthelist
  48. *@paramstartthestartangleatwhichtherotationmustbegin
  49. *@paramendtheendangleoftherotation
  50. */
  51. privatevoidapplyRotation(intposition,floatstart,floatend){
  52. //计算中心点
  53. finalfloatcenterX=mContainer.getWidth()/2.0f;
  54. finalfloatcenterY=mContainer.getHeight()/2.0f;
  55. //Createanew3Drotationwiththesuppliedparameter
  56. //Theanimationlistenerisusedtotriggerthenextanimation
  57. finalRotate3dAnimationrotation=
  58. newRotate3dAnimation(start,end,centerX,centerY,310.0f,true);
  59. rotation.setDuration(500);
  60. rotation.setFillAfter(true);
  61. rotation.setInterpolator(newAccelerateInterpolator());
  62. //设置监听
  63. rotation.setAnimationListener(newDisplayNextView(position));
  64. mContainer.startAnimation(rotation);
  65. }
  66. publicvoidonItemClick(AdapterViewparent,Viewv,intposition,longid){
  67. //设置ImageView
  68. mImageView.setImageResource(PHOTOS_RESOURCES[position]);
  69. applyRotation(position,0,90);
  70. }
  71. //点击图像时,返回listview
  72. publicvoidonClick(Viewv){
  73. applyRotation(-1,180,90);
  74. }
  75. /**
  76. *Thisclasslistensfortheendofthefirsthalfoftheanimation.
  77. *Itthenpostsanewactionthateffectivelyswapstheviewswhenthecontainer
  78. *isrotated90degreesandthusinvisible.
  79. */
  80. privatefinalclassDisplayNextViewimplementsAnimation.AnimationListener{
  81. privatefinalintmPosition;
  82. privateDisplayNextView(intposition){
  83. mPosition=position;
  84. }
  85. publicvoidonAnimationStart(Animationanimation){
  86. }
  87. //动画结束
  88. publicvoidonAnimationEnd(Animationanimation){
  89. mContainer.post(newSwapViews(mPosition));
  90. }
  91. publicvoidonAnimationRepeat(Animationanimation){
  92. }
  93. }
  94. /**
  95. *Thisclassisresponsibleforswappingtheviewsandstartthesecond
  96. *halfoftheanimation.
  97. */
  98. privatefinalclassSwapViewsimplementsRunnable{
  99. privatefinalintmPosition;
  100. publicSwapViews(intposition){
  101. mPosition=position;
  102. }
  103. publicvoidrun(){
  104. finalfloatcenterX=mContainer.getWidth()/2.0f;
  105. finalfloatcenterY=mContainer.getHeight()/2.0f;
  106. Rotate3dAnimationrotation;
  107. if(mPosition>-1){
  108. //显示ImageView
  109. mPhotosList.setVisibility(View.GONE);
  110. mImageView.setVisibility(View.VISIBLE);
  111. mImageView.requestFocus();
  112. rotation=newRotate3dAnimation(90,180,centerX,centerY,310.0f,false);
  113. }else{
  114. //返回listview
  115. mImageView.setVisibility(View.GONE);
  116. mPhotosList.setVisibility(View.VISIBLE);
  117. mPhotosList.requestFocus();
  118. rotation=newRotate3dAnimation(90,0,centerX,centerY,310.0f,false);
  119. }
  120. rotation.setDuration(500);
  121. rotation.setFillAfter(true);
  122. rotation.setInterpolator(newDecelerateInterpolator());
  123. //开始动画
  124. mContainer.startAnimation(rotation);
  125. }
  126. }
  127. }

更多相关文章

  1. Android之帧动画与补间动画的使用
  2. 【极客学院每日一课】Android系列之三:Android 布局动画
  3. android textview背景色动画
  4. android 自带的动画,实现左右切屏效果
  5. Android 帧动画
  6. Android 动画之RotateAnimation

随机推荐

  1. Android中findViewById返回为空null的快
  2. Android(安卓)模拟器方向键和键盘方向键
  3. Android(安卓)SDK下载和更新失败的解决方
  4. Android学习笔记三
  5. Android(安卓)源码编译make的错误处理
  6. Android(安卓)设置图片的四个角 为圆角
  7. Android读写文件源码
  8. 【Android】兼容Scrollview的可动态设置
  9. android studio build报错error: undefin
  10. Android让所有应用都竖屏显示或者横屏显