Android 3D Rotation animation effect Decomposition

Source: Internet
Author: User
Tags in degrees

This article mainly introduces how to achieve the 3D Rotation effect of the View. The main principle is to rotate around the Y axis, and there is an in-depth zooming in the Z axis.

The demo has the following highlights:
1. Custom rotation Animation
2. After the animation is completed, reset the ImageView
Let's take a look at the running effect of the program:

1. Custom Animation
Here we implement a Rotate3dAnimation class, which extends the Animation class and overwrites the applyTransformation () method to provide matrix transformation at the specified time. In this method, you can use the Camera class to obtain a matrix that rotates around the Y axis and set this matrix to a Transformation object. The specific implementation code is as follows:Copy codeThe Code is as follows: @ 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. How to use this animation class
In the Activity, we have two imageviews of the same size, all of which are placed in FrameLayout, so that their positions overlap and animation is performed on the top ImageView (rotation angle from 0 to 90 ), after the animation is completed, the following ImageView is animated (the rotation angle ranges from 90 to 180). Here, you need to control the corresponding ImageView to hide or display.
The listener Implementation of the animation is as follows:Copy codeThe Code is as follows: 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 ){
}
}

After the animation is completed, run the following code:Copy codeThe Code is as follows: 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 );
}
}

Click the Button to implement event processing:Copy codeThe Code is as follows: @ Override
Public void onClick (View v)
{
MCenterX = mContainer. getWidth ()/2;
MCenterY = mContainer. getHeight ()/2;
GetDepthZ ();
ApplyRotation (mStartAnimView, 0, 90 );
}

The implementation of applyRotation is as follows:Copy codeThe Code is as follows: 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. The complete code is as follows:
Rotate3dAnimActivity. javaCopy codeThe Code is as follows: 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, 300366f );
}
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 implements tively 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.xmlCopy codeThe Code is as follows: <? 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. javaCopy codeThe Code is as follows: 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 already med 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 saved med. The length
* Of the translation can be specified, as well as whether the translation
* Shoshould 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 shoshould 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 );
}
}

Ladies and gentlemen, please think about the following two sentences in order to implement the applyTransformation method:
Matrix. preTranslate (-centerX,-centerY );
Matrix. postTranslate (centerX, centerY );

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.