android的API Demo提供了很多有趣+有用的Demo,本系列将学习基于4.4.2版本的API,其中涉及到的代码大部分是出于android 自带的Demo,本人根据自己的学习、理解,加以注释。

public class Rotate3DAnimation extends Animation {private final float mFromDegrees;//开始角度    private final float mToDegrees;//结束角度    private final float mCenterX;//中心X点    private final float mCenterY;//中心Y点    private final float mDepthZ;//深度Z,越大缩放越明显    private final boolean mReverse;//是否相反,true:视角由近到远 false:视角由远到近(缩放效果)    private Camera mCamera;   public Rotate3DAnimation(float mFromDegrees, float mToDegrees,float mCenterX, float mCenterY, float mDepthZ, boolean mReverse) {super();this.mFromDegrees = mFromDegrees;this.mToDegrees = mToDegrees;this.mCenterX = mCenterX;this.mCenterY = mCenterY;this.mDepthZ = mDepthZ;this.mReverse = mReverse;}@Overridepublic void initialize(int width, int height, int parentWidth,int parentHeight) {super.initialize(width, height, parentWidth, parentHeight);mCamera=new Camera();// 动画时间setDuration(500);// 动画完成后保持完成的状态setFillAfter(true);}//当动画开始时,会不断调用applyTransformation,这个过程是动态的,不断在变化    //interpolatedTime 代表当前方法掉用时,动画进行的一个时间点,这个值的范围是0到1,也就是说动画刚开始的时候//传进来的interpolatedTime为0,动画进行中的时候,传进来的是0到1之间的小数,动画结束的时候传进来的是1。@Overrideprotected void applyTransformation(float interpolatedTime, Transformation t) {final float fromDegrees = mFromDegrees;//计算每次变化的角度float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);final float centerX = mCenterX;    final float centerY = mCenterY;    final Camera camera = mCamera;    //获取原始矩阵    final Matrix matrix = t.getMatrix();        camera.save();    if(mReverse){//视图离镜头越来越远,即缩小视角    camera.translate(0.0f, 0.0f, mDepthZ*interpolatedTime);    }else{//视图离镜头越来越近,即放大视角    camera.translate(0.0f, 0.0f, mDepthZ*(1.0f-interpolatedTime));    }    //以Y轴为旋转中心轴,旋转degrees角度    camera.rotateY(degrees);    camera.getMatrix(matrix);    camera.restore();    //pre是前乘,参数给出的矩阵乘以当前的矩阵。在旋转之前,先平移(-centerX, -centerY)    matrix.preTranslate(-centerX, -centerY);    //post是后乘,当前的矩阵乘以参数给出的矩阵。旋转之后,在平移(centerX, centerY)    matrix.postTranslate(centerX, centerY);    //总的来说,就是在绕Y轴旋转之前,先把旋转中心点从(0,0)移到(centerX,centerY),然后以Y轴为轴线,    //(centerX,centerY)为轴心旋转degrees后,将中心点复原为(0,0),这样看起来就是以视图的中心,绕Y轴旋转了。}}

Rotate3DAnimation是封装了3D旋转动画效果的类,注释是我对其的理解

public class Transition3dActivity extends Activity implementsOnItemClickListener, OnClickListener {private ListView mPhotosList;private ViewGroup mContainer;private ImageView mImageView;// Names of the photos we show in the listprivate static final String[] PHOTOS_NAMES = new String[] { "Lyon","Livermore", "Tahoe Pier", "Lake Tahoe", "Grand Canyon", "Bodie" };// 显示的图片资源private static final int[] PHOTOS_RESOURCES = new int[] {R.drawable.photo1, R.drawable.photo2, R.drawable.photo3,R.drawable.photo4, R.drawable.photo5, R.drawable.photo6 };@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.animations_main_screen);mPhotosList = (ListView) findViewById(android.R.id.list);mImageView = (ImageView) findViewById(R.id.picture);mContainer = (ViewGroup) findViewById(R.id.container);// Prepare the ListViewfinal ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, PHOTOS_NAMES);mPhotosList.setAdapter(adapter);mPhotosList.setOnItemClickListener(this);// Prepare the ImageViewmImageView.setClickable(true);mImageView.setFocusable(true);mImageView.setOnClickListener(this);// Since we are caching large views, we want to keep their cache// between each animation(缓存)mContainer.setPersistentDrawingCache(ViewGroup.PERSISTENT_ANIMATION_CACHE);}/** * 3D旋转视图 2014-11-13 下午1:31:06 *  * @param position *            item位置 * @param start *            开始角度 * @param end *            结束角度 * @TODO */private void applyRotation(int position, float start, float end) {// 获取视图中心点float centerX = mContainer.getWidth() / 2.0f;float centerY = mContainer.getHeight() / 2.0f;// 构建3D旋转动画对象final Rotate3DAnimation rotation = new Rotate3DAnimation(start, end,centerX, centerY, 310.0f, true);// 设置动画速度变化曲线为加速rotation.setInterpolator(new AccelerateInterpolator());// 动画监听rotation.setAnimationListener(new DisplayNextView(position));mContainer.startAnimation(rotation);}@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position,long id) {mImageView.setImageResource(PHOTOS_RESOURCES[position]);// 每次点击item时,将mContainer根布局旋转角度从0到90(可将自己的左手正面朝上当作mContainer容器,逆时针旋转90度的过程)---①applyRotation(position, 0, 90);}/** * This class listens for the end of the first half of the animation. It * then posts a new action that effectively swaps the views when the * container is rotated 90 degrees and thus invisible. */private final class DisplayNextView implements Animation.AnimationListener {private final int mPosition;private DisplayNextView(int position) {mPosition = position;}public void onAnimationStart(Animation animation) {}public void onAnimationEnd(Animation animation) {// 当ListView动画结束时,ListView隐藏,不显示,此时图片开始显示mContainer.post(new SwapViews(mPosition));}public void onAnimationRepeat(Animation animation) {}}/** * This class is responsible for swapping the views and start the second * half of the animation. */private final class SwapViews implements Runnable {private final int mPosition;public SwapViews(int position) {mPosition = position;}public void run() {final float centerX = mContainer.getWidth() / 2.0f;final float centerY = mContainer.getHeight() / 2.0f;Rotate3DAnimation rotation;if (mPosition > -1) {// 点击的是itemmPhotosList.setVisibility(View.GONE);mImageView.setVisibility(View.VISIBLE);mImageView.requestFocus();// 由于第①步的旋转,此时mContainer是处于90度的,再次旋转90度,从90到180,// 等于此时的mContainer已经旋转了180度,处于“背面”向上-----②// (相当于左手手心起始向右,向下转动的过程,直至手心向下,手背在上面,而这个过程正是图片从无到有,ListView从有到无的过程)rotation = new Rotate3DAnimation(90, 180, centerX, centerY,310.0f, false);} else {// 点击的是ImageView(mPosition=-1)mImageView.setVisibility(View.GONE);mPhotosList.setVisibility(View.VISIBLE);mPhotosList.requestFocus();// 由于第③步,此时的mContainer处于90度,然后再次旋转90度,从90到0,复原了初始状态(左手手心向右顺时针旋转90度至手心向上的原始状态)rotation = new Rotate3DAnimation(90, 0, centerX, centerY,310.0f, false);}// 设置动画速度变化曲线为减速rotation.setInterpolator(new DecelerateInterpolator());mContainer.startAnimation(rotation);}}@Overridepublic void onClick(View v) {// 由于第②步的结果,使mContainer处于旋转了180的状态,当点击ImageView时,使mContainer状态复原回去// 从180到旋转到90-----③(当点击图片时,左手旋转的动作是一个相反的过程,即从左手手心向下,手背在上的状态,顺时针旋转90度至手心向右)applyRotation(-1, 180, 90);}}

xml布局animations_main_screen.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/container"    android:layout_width="match_parent"    android:layout_height="match_parent">    <ListView        android:id="@android:id/list"        android:persistentDrawingCache="animation|scrolling"        android:layout_width="match_parent"        android:layout_height="match_parent"        />    <ImageView        android:id="@+id/picture"        android:scaleType="fitCenter"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:visibility="gone" /></FrameLayout>

效果图:


更多相关文章

  1. Android(安卓)Animation动画 控制动画的执行效果,速度等
  2. Android属性动画-Property Animation(三) 使用ValueAnimator完成
  3. Android属性动画ObjectAnimator源码简单分析
  4. 很实用的android压缩图片的算法
  5. android UI进阶之弹窗的使用(2)--实现通讯录的弹窗效果
  6. android三种动画详解
  7. android设置横屏和竖屏的方法
  8. Android播放GIF动画
  9. Android除了三大动画,还有哪些动画?

随机推荐

  1. Android实现分享(Share)功能
  2. Android基础 : Android(安卓)Service
  3. Android(安卓)数字签名学习笔记
  4. 很赞的Android架构组件 Android(安卓)Arc
  5. Android中的资源与国际化
  6. Android编译系统入门(一)
  7. Android中的Button自定义点击效果之改变
  8. Android多线程下载远程图片
  9. 简单的使用腾讯X5内核浏览器替代Android
  10. 为什么Android没有iOS那么顺滑