使用XML在Android中创建3D翻转动画

时间:2011-10-16 16:25:49

标签: android xml animation 3d

我使用this android tutorial创建了视图的3D翻转 但是,我已经以编程方式完成了它,如果可能的话,我想在xml中完成所有操作。我不是在谈论简单地将视图缩小到中间然后退出,而是实际的3D翻转。

这可以通过xml吗?

8 个答案:

答案 0 :(得分:56)

以下是答案,但它仅适用于3.0及以上版本。

1)创建一个名为“animator”的新资源文件夹。

2)创建一个新的.xml文件,我称之为“翻转”。使用以下xml代码:

<?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>

不,objectAnimator标签不以大写“O”开头。

3)使用以下代码启动动画:

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

我从here得到了所有这些。

答案 1 :(得分:25)

由于这个问题的答案相当过时,这里是一个更依赖ValueAnimators的现代解决方案。 这个解决方案实现了一个真实的,视觉上吸引人的3D翻转,因为它不仅可以翻转视图,还可以在翻转时进行缩放(Apple就是这样做的。)

首先我们设置ValueAnimator:

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

相应的更新监听器:

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

那就是它!

完成此设置后,您可以通过调用

来翻转视图
mFlipAnimator.start();

通过调用

来反转翻转
mFlipAnimator.reverse();

如果要检查视图是否被翻转,请实现并调用此函数:

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

您还可以通过实施此方法来检查视图当前是否正在翻转:

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

您可以结合上述功能来实现一个很好的功能来切换翻转,具体取决于是否翻转:

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

那就是它!简单易行。享受!

答案 2 :(得分:7)

我创建了一个简单的程序来创建视图翻转,如:

enter image description here

在Activity中你必须创建这个方法,以便在视图中添加flip_rotation。

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

为此,你必须复制用于提供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);

    }

}

答案 3 :(得分:4)

教程或om252345的链接不会产生可信的3D翻转。在y轴上的简单旋转不是在iOS中完成的。还需要缩放效果来创建漂亮的翻转感觉。为此,请查看this example。 还有一个视频here

答案 4 :(得分:4)

使用资源动画翻转图像的更好解决方案之一如下: -

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

答案 5 :(得分:3)

  1. 最简单的方法是使用ViewPropertyAnimator

    mImageView.animate().rotationY(360f);
    

    使用流畅的界面,您可以构建更复杂和令人兴奋的动画。 例如。你可以启用硬件加速,只需调用withLayer()方法(API 16)。更多here

  2. 如果您想了解如何制作3D轻弹动画,请关注herehere

  3. 我仅为研究实施了自己的解决方案。它包括:取消,加速,支持API&gt; = 15并基于Property Animation。 整个动画包括4个部分,每侧2个。 每个objectAnimator都有一个侦听器,用于定义当前动画索引,并表示onAnimationStart中的图像和onAnimationCancel中的当前播放时间值。 它看起来像

    mQuarterAnim1.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationStart(Animator animation) {
            mQuarterCurrentAnimStartIndex = QUARTER_ANIM_INDEX_1;
            mImageView.setImageResource(mResIdFrontCard);
        }
    
        @Override
        public void onAnimationCancel(Animator animation) {
            mQuarterCurrentAnimPlayTime = ((ObjectAnimator) animation).getCurrentPlayTime();
        }
    });
    

    用于开始设置呼叫

    mAnimatorSet.play(mQuarterAnim1).before(mQuarterAnim2)
    

    如果AnimatorSet被取消,我们可以计算delta并依赖当前索引动画和当前播放时间值运行反向动画。

    long degreeDelta = mQuarterCurrentAnimPlayTime * QUARTER_ROTATE / QUARTER_ANIM_DURATION;
    
    if (mQuarterCurrentAnimStartIndex == QUARTER_ANIM_INDEX_1) {
        mQuarterAnim4.setFloatValues(degreeDelta, QUARTER_FROM_1);
        mQuarterAnim4.setDuration(mQuarterCurrentAnimPlayTime);
    
        mAnimatorSet.play(mQuarterAnim4);
    }
    
  4. 您可以找到here

    的完整代码段

答案 6 :(得分:1)

只需将要为其设置动画的视图替换为viewToFlip。

/

答案 7 :(得分:0)

增加了A. Steenbergen的出色答案。翻转相同的视图时(例如更新TextView),我删除了构造函数中的View.Visibility更改,以使过渡更加平滑。

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