转自:http://lzyfn123.iteye.com/blog/1426844

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. finalArrayAdapteradapter=newArrayAdapter(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之ViewFlipper实现左右滑动动画效果
  2. android listview每个item定义动画呈现
  3. Android启动画面Splash
  4. Android创建逐帧动画的方式
  5. android 加载进度条动画
  6. android实现播放器反射性动画效果
  7. Android显示GIF动画完整示例(一)
  8. [Android] Android Tweened Animations动画使用详解二

随机推荐

  1. 【OCP最新题库解析(052)--题18】 Which t
  2. 【OCP最新题库解析(052)--题16】Your dat
  3. 【博客大赛】ansible 企业级自动化运维实
  4. 类的重定向,命名空间和内容的访问
  5. 0414作业-$.get,$.post,$ajax与Vue基本术
  6. Google Play上出现了针对移动设备的恶意
  7. 用富兰克林学习写作的方法来研究计算机方
  8. 【小麦苗课堂】高可用培训(RAC+DG+OGG)
  9. 【优化】COUNT(1)、COUNT(*)、COUNT(常量
  10. 【故障处理】DBCA建库诡异问题处理--rac