Android 3D旋转动画效果实现分解

这篇文章主要介绍一下如何实现View的3D旋转效果,实现的主要原理就是围绕Y轴旋转,同时在Z轴方面上有一个深入的缩放。

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

1,自定义旋转动画

2,动画做完后,重置ImageView

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

 

1,自定义动画类

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

复制代码 代码如下:

@Override

protected 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));

}

camera.rotateY(degrees);

camera.getMatrix(matrix);

camera.restore();

matrix.preTranslate(-centerX, -centerY);

matrix.postTranslate(centerX, centerY);

}

2,如何使用这个动画类

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

动画的listener实现如下:

复制代码 代码如下:

private final class DisplayNextView implements Animation.AnimationListener {

public void onAnimationStart(Animation animation) {

}

public void onAnimationEnd(Animation animation) {

mContainer.post(new SwapViews());

}

public void onAnimationRepeat(Animation animation) {

}

}

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

复制代码 代码如下:

private final class SwapViews implements Runnable

{

@Override

public void run()

{

mImageView1.setVisibility(View.GONE);

mImageView2.setVisibility(View.GONE);

mIndex++;

if (0 == mIndex % 2)

{

mStartAnimView = mImageView1;

}

else

{

mStartAnimView = mImageView2;

}

mStartAnimView.setVisibility(View.VISIBLE);

mStartAnimView.requestFocus();

Rotate3dAnimation rotation = new Rotate3dAnimation(

-90,

0,

mCenterX,

mCenterY, mDepthZ, false);

rotation.setDuration(mDuration);

rotation.setFillAfter(true);

rotation.setInterpolator(new DecelerateInterpolator());

mStartAnimView.startAnimation(rotation);

}

}

点击Button的事件处理实现:

复制代码 代码如下:

@Override

public void onClick(View v)

{

mCenterX = mContainer.getWidth() / 2;

mCenterY = mContainer.getHeight() / 2;

getDepthZ();

applyRotation(mStartAnimView, 0, 90);

}

applyRotation的实现如下:

复制代码 代码如下:

private void applyRotation(View animView, float startAngle, float toAngle)

{

float centerX = mCenterX;

float centerY = mCenterY;

Rotate3dAnimation rotation = new Rotate3dAnimation(

startAngle, toAngle, centerX, centerY, mDepthZ, true);

rotation.setDuration(mDuration);

rotation.setFillAfter(true);

rotation.setInterpolator(new AccelerateInterpolator());

rotation.setAnimationListener(new DisplayNextView());

animView.startAnimation(rotation);

}

3,完整代码如下

Rotate3dAnimActivity.java

复制代码 代码如下:

public class Rotate3dAnimActivity extends Activity

{

ImageView mImageView1 = null;

ImageView mImageView2 = null;

ImageView mStartAnimView = null;

View mContainer = null;

int mDuration = 500;

float mCenterX = 0.0f;

float mCenterY = 0.0f;

float mDepthZ = 0.0f;

int mIndex = 0;

@Override

public void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.rotate_anim);

mImageView1 = (ImageView) findViewById(R.id.imageView1);

mImageView2 = (ImageView) findViewById(R.id.imageView2);

mContainer = findViewById(R.id.container);

mStartAnimView = mImageView1;

findViewById(R.id.button1).setOnClickListener(new View.OnClickListener()

{

@Override

public void onClick(View v)

{

mCenterX = mContainer.getWidth() / 2;

mCenterY = mContainer.getHeight() / 2;

getDepthZ();

applyRotation(mStartAnimView, 0, 90);

}

});

InputMethodManager imm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);

imm.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);

}

private void getDepthZ()

{

EditText editText = (EditText) findViewById(R.id.edit_depthz);

String string = editText.getText().toString();

try

{

mDepthZ = (float)Integer.parseInt(string);

//mDepthZ = Math.min(mDepthZ, 300.0f);

}

catch (Exception e)

{

e.printStackTrace();

}

}

private void applyRotation(View animView, float startAngle, float toAngle)

{

float centerX = mCenterX;

float centerY = mCenterY;

Rotate3dAnimation rotation = new Rotate3dAnimation(

startAngle, toAngle, centerX, centerY, mDepthZ, true);

rotation.setDuration(mDuration);

rotation.setFillAfter(true);

rotation.setInterpolator(new AccelerateInterpolator());

rotation.setAnimationListener(new DisplayNextView());

animView.startAnimation(rotation);

}

/**

* 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 {

public void onAnimationStart(Animation animation) {

}

public void onAnimationEnd(Animation animation) {

mContainer.post(new SwapViews());

}

public void onAnimationRepeat(Animation animation) {

}

}

private final class SwapViews implements Runnable

{

@Override

public void run()

{

mImageView1.setVisibility(View.GONE);

mImageView2.setVisibility(View.GONE);

mIndex++;

if (0 == mIndex % 2)

{

mStartAnimView = mImageView1;

}

else

{

mStartAnimView = mImageView2;

}

mStartAnimView.setVisibility(View.VISIBLE);

mStartAnimView.requestFocus();

Rotate3dAnimation rotation = new Rotate3dAnimation(

-90,

0,

mCenterX,

mCenterY, mDepthZ, false);

rotation.setDuration(mDuration);

rotation.setFillAfter(true);

rotation.setInterpolator(new DecelerateInterpolator());

mStartAnimView.startAnimation(rotation);

}

}

}

rotate_anim.xml

复制代码 代码如下:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:orientation="vertical" >

<Button

android:id="@+id/button1"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_margin="20dp"

android:text="Do 3d animation" />

<TextView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginLeft="20px"

android:text="Input Depth on Z axis. [0, 300]"

/>

<EditText

android:id="@+id/edit_depthz"

android:layout_width="200dp"

android:layout_height="wrap_content"

android:layout_margin="20dp"

android:text="0"/>

<FrameLayout

android:id="@+id/container"

android:layout_width="wrap_content"

android:layout_height="wrap_content">

<ImageView

android:id="@+id/imageView1"

android:layout_width="200dp"

android:layout_height="200dp"

android:layout_margin="20dp"

android:src="@drawable/f" />

<ImageView

android:id="@+id/imageView2"

android:layout_width="200dp"

android:layout_height="200dp"

android:layout_margin="20dp"

android:src="@drawable/s"

android:visibility="gone"/>

</FrameLayout>

</LinearLayout>

Rotate3dAnimation.java

复制代码 代码如下:

package com.nj1s.lib.anim;

import android.graphics.Camera;

import android.graphics.Matrix;

import android.view.animation.Animation;

import android.view.animation.Transformation;

/**

* An animation that rotates the view on the Y axis between two specified angles.

* This animation also adds a translation on the Z axis (depth) to improve the effect.

*/

public class Rotate3dAnimation extends Animation {

private final float mFromDegrees;

private final float mToDegrees;

private final float mCenterX;

private final float mCenterY;

private final float mDepthZ;

private final boolean mReverse;

private Camera mCamera;

/**

* Creates a new 3D rotation on the Y axis. The rotation is defined by its

* start angle and its end angle. Both angles are in degrees. The rotation

* is performed around a center point on the 2D space, definied by a pair

* of X and Y coordinates, called centerX and centerY. When the animation

* starts, a translation on the Z axis (depth) is performed. The length

* of the translation can be specified, as well as whether the translation

* should be reversed in time.

*

* @param fromDegrees the start angle of the 3D rotation

* @param toDegrees the end angle of the 3D rotation

* @param centerX the X center of the 3D rotation

* @param centerY the Y center of the 3D rotation

* @param reverse true if the translation should be reversed, false otherwise

*/

public Rotate3dAnimation(float fromDegrees, float toDegrees,

float centerX, float centerY, float depthZ, boolean reverse) {

mFromDegrees = fromDegrees;

mToDegrees = toDegrees;

mCenterX = centerX;

mCenterY = centerY;

mDepthZ = depthZ;

mReverse = reverse;

}

@Override

public void initialize(int width, int height, int parentWidth, int parentHeight) {

super.initialize(width, height, parentWidth, parentHeight);

mCamera = new Camera();

}

@Override

protected 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));

}

camera.rotateY(degrees);

camera.getMatrix(matrix);

camera.restore();

matrix.preTranslate(-centerX, -centerY);

matrix.postTranslate(centerX, centerY);

}

}

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

matrix.preTranslate(-centerX, -centerY);

matrix.postTranslate(centerX, centerY);

时间: 2024-10-06 19:47:19

Android 3D旋转动画效果实现分解的相关文章

Flash AS3制作交互式3D旋转动画效果

  效果演示: 使图标具有交互性: 当鼠标单击某个图标时使之旋转,并让图标显示在屏幕的最前面. //定义旋转的最终角度 var endAngle:Number = 90; //保存已经旋转的角度 var tempAngle:Number = 0; //保存旋转的状态 var isRotating:Boolean = true; //注册图标的单击事件 mc.addEventListener(MouseEvent.MOUSE_DOWN,startRotation); //定义侦听器函数 funct

Flash教程:制作3D旋转动画效果

  本教程着重于代码的编写,版本AS 3.0.只要制作一个旋转的3D球,图形元件的制作不作讲解,请参看有关教程. include "Math2.as" //图片容器 var menu:Sprite=new Sprite(); //使图标移动 menu.x = 300; menu.y = 200; //注册事件侦听器 menu.addEventListener(Event.ENTER_FRAME,moveMenu); this.addChild(menu); //椭圆在x 和y 轴上的截

动画效果-android 一个旋转动画的效果,未完全展示

问题描述 android 一个旋转动画的效果,未完全展示 ndroid,我对一个按钮button做点击事件,点击button后将一张图片旋转90度,但是频繁点击的过程中,总会有几次图片没有旋转到90度,或者压根就没有旋转. 我在旋转动画的监听onAnimationEnd()方法里面,输出了debug,代码确实执行到这里了,为什么执行动画后,页面效果看不见. 请有经验和知道状况的朋友,指导下,谢谢 解决方案 最好用属性动画做,如果是需要完整执行每个点击响应就每次都起个线程post到ui进程来做动画

Android图片翻转动画效果

http://blog.csdn.net/hnlshzx2008/article/details/7846621 Android中并没有提供直接做3D翻转的动画,所以关于3D翻转的动画效果需要我们自己实现,那么我们首先来分析一下Animation 和 Transformation. Animation动画的主要接口,其中主要定义了动画的 一些属性比如开始时间,持续时间,是否重复播放等等.而Transformation中则包含一个矩阵和alpha值,矩阵是用来做平移,旋转和缩放动画 的,而alph

Android补间动画效果

Android的SDK提供了三种类型的动画,分别是补间动画.逐帧动画和插值属性动画.下面先介绍第一种动画效果-补间动画. 补间动画可以应用于View,让开发者可以定义一些关于大小.位置.旋转和透明度的改变效果,达到让View的内容动起来的效果. 补间动画是使用Animation类创建的,它有4个直接子类,分别实现不同的动画效果,分别为: AlphaAnimation 渐变透明度动画效果,即淡入淡出效果 ScaleAnimation 渐变尺寸伸缩动画效果,即缩放效果 TranslateAnimat

jQuery实现图像旋转动画效果_jquery

废话不多说了,直接给大家贴代码了,具体代码如下所示: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <tit

Android GridView实现动画效果实现代码

Android GridView实现动画效果 项目中用到的一些动画,GridView的Item依次从屏幕外飞入到相应位置,附上相关代码: MainActivity.Java package com.mundane.gridanimationdemo; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.view.ani

Android实现带动画效果的可点击展开TextView

本文为大家分享了Android实现带动画效果的可点击展开TextView 制作代码,效果图: 收起(默认)效果: 点击展开后的效果: 源码: 布局: <?xml version="1.0" encoding="utf-8"?> <LinearLayout android:id="@+id/activity_main" xmlns:android="http://schemas.android.com/apk/res/a

Android 吸入动画效果实现分解_Android

Android 吸入动画效果详解 .  这里,我要介绍的是如何在Android上面实现一个类似的效果.先看看我实现的效果图.  上图演示了动画的某几帧,其中从1 - 4,演示了图片从原始图形吸入到一个点(红色标识). 实现这样的效果,我们利用了Canvas.drawBitmapMesh()方法,这里涉及到了一个Mesh的概念. 2,Mesh的概念 Mesh表示网格,说得通俗一点,可以将画板想像成一张格子布,在这个张布上绘制图片.对于一个网格端点均匀分布的网格来说,横向有meshWidth + 1