Creating a 3D flip animation in Android using XML

57,549

Solution 1

Here is the answer, though it only works with 3.0 and above.

1) Create a new resources folder called "animator".

2) Create a new .xml file which I will call "flipping". Use the following xml code:

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:valueFrom="0" android:valueTo="360" android:propertyName="rotationY" >
</objectAnimator>

No, the objectAnimator tags do not start with an uppercase "O".

3) Start the animation with the following code:

ObjectAnimator anim = (ObjectAnimator) AnimatorInflater.loadAnimator(mContext, R.animator.flipping); 
anim.setTarget(A View Object reference goes here i.e. ImageView);
anim.setDuration(3000);
anim.start();

I got all this from here.

Solution 2

Since the answers to this question are fairly dated, here is a more modern solution relying on ValueAnimators. This solution implements a true, visually appealing 3D-flip, because it not just flips the view, but also scales it while it is flipping (this is how Apple does it).

First we set up the ValueAnimator:

mFlipAnimator = ValueAnimator.ofFloat(0f, 1f);
mFlipAnimator.addUpdateListener(new FlipListener(frontView, backView));

And the corresponding update listener:

public class FlipListener implements ValueAnimator.AnimatorUpdateListener {

    private final View mFrontView;
    private final View mBackView;
    private boolean mFlipped;

    public FlipListener(final View front, final View back) {
        this.mFrontView = front;
        this.mBackView = back;
        this.mBackView.setVisibility(View.GONE);
    }

    @Override
    public void onAnimationUpdate(final ValueAnimator animation) {
        final float value = animation.getAnimatedFraction();
        final float scaleValue = 0.625f + (1.5f * (value - 0.5f) * (value - 0.5f));

        if(value <= 0.5f){
            this.mFrontView.setRotationY(180 * value);
            this.mFrontView.setScaleX(scaleValue);
            this.mFrontView.setScaleY(scaleValue);
            if(mFlipped){
                setStateFlipped(false);
            }
        } else {
            this.mBackView.setRotationY(-180 * (1f- value));
            this.mBackView.setScaleX(scaleValue);
            this.mBackView.setScaleY(scaleValue);
            if(!mFlipped){
                setStateFlipped(true);
            }
        }
    }

    private void setStateFlipped(boolean flipped) {
        mFlipped = flipped;
        this.mFrontView.setVisibility(flipped ? View.GONE : View.VISIBLE);
        this.mBackView.setVisibility(flipped ? View.VISIBLE : View.GONE);
    }
}

That's it!

After this setup you can flip the views by calling

mFlipAnimator.start();

and reverse the flip by calling

mFlipAnimator.reverse();

If you want to check if the view is flipped, implement and call this function:

private boolean isFlipped() {
    return mFlipAnimator.getAnimatedFraction() == 1;
}

You can also check if the view is currently flipping by implementing this method:

private boolean isFlipping() {
    final float currentValue = mFlipAnimator.getAnimatedFraction();
    return (currentValue < 1 && currentValue > 0);
}

You can combine the above functions to implement a nice function to toggle the flip, depending on if it is flipped or not:

private void toggleFlip() {
    if(isFlipped()){
        mFlipAnimator.reverse();
    } else {
        mFlipAnimator.start();
    }
}

That's it! Simple and easy. Enjoy!

Solution 3

I have created a simple program for creating flip of view like :

enter image description here

In Activity you have to create this method, for adding flip_rotation in view.

private void applyRotation(View view) 
{
    final Flip3dAnimation rotation = new Flip3dAnimation(view);
    rotation.applyPropertiesInRotation();
    view.startAnimation(rotation);
}

for this, you have to copy main class used to provide flip_rotation.

import android.graphics.Camera;
import android.graphics.Matrix;
import android.util.Log;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.Transformation;

public class Flip3dAnimation extends Animation {
    private final float mFromDegrees;
    private final float mToDegrees;
    private final float mCenterX;
    private final float mCenterY;
    private Camera mCamera;

    public Flip3dAnimation(View view) {
        mFromDegrees = 0;
        mToDegrees = 720;
        mCenterX = view.getWidth() / 2.0f;
        mCenterY = view.getHeight() / 2.0f;
    }

    @Override
    public void initialize(int width, int height, int parentWidth,
            int parentHeight) {
        super.initialize(width, height, parentWidth, parentHeight);
        mCamera = new Camera();
    }

    public void applyPropertiesInRotation()
    {
        this.setDuration(2000);
        this.setFillAfter(true);
        this.setInterpolator(new AccelerateInterpolator());
    }

    @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();

        Log.e("Degree",""+degrees) ;
        Log.e("centerX",""+centerX) ;
        Log.e("centerY",""+centerY) ;

        camera.rotateY(degrees);

        camera.getMatrix(matrix);
        camera.restore();

        matrix.preTranslate(-centerX, -centerY);
        matrix.postTranslate(centerX, centerY);

    }

}

Solution 4

One of the better solution to flip the image with out use of the resource animation , is as follow:-

  ObjectAnimator animation = ObjectAnimator.ofFloat(YOUR_IMAGEVIEW, "rotationY", 0.0f, 360f);  // HERE 360 IS THE ANGLE OF ROTATE, YOU CAN USE 90, 180 IN PLACE OF IT,  ACCORDING TO YOURS REQUIREMENT 

  animation.setDuration(500); // HERE 500 IS THE DURATION OF THE ANIMATION, YOU CAN INCREASE OR DECREASE ACCORDING TO YOURS REQUIREMENT
  animation.setInterpolator(new AccelerateDecelerateInterpolator());
  animation.start();

Solution 5

The tutorial or the link by om252345 don't produce believable 3D flips. A simple rotation on the y-axis isn't what's done in iOS. The zoom effect is also needed to create that nice flip feel. For that, take a look at this example. There is also a video here.

Share:
57,549
Swifty McSwifterton
Author by

Swifty McSwifterton

Updated on July 09, 2022

Comments

  • Swifty McSwifterton
    Swifty McSwifterton almost 2 years

    I have created a 3D flip of a view using this android tutorial However, I have done it programmatically and I would like to do it all in xml, if possible. I am not talking about simply shrinking a view to the middle and then back out, but an actual 3D flip.

    Is this possible via xml?