Создание 3D-анимации в Android с использованием XML - PullRequest
24 голосов
/ 16 октября 2011

Я создал трехмерное отражение вида, используя это руководство для Android Тем не менее, я сделал это программно, и я хотел бы сделать все это в XML, если это возможно. Я говорю не просто об уменьшении изображения до середины и затем назад, а о реальном трехмерном отражении.

Возможно ли это через xml?

Ответы [ 8 ]

56 голосов
/ 13 ноября 2011

Вот ответ, хотя он работает только с 3.0 и выше.

1) Создайте новую папку ресурсов под названием «аниматор».

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

Я получил все это от здесь .

25 голосов
/ 10 февраля 2015

Поскольку ответы на этот вопрос довольно устарели, вот более современное решение, основанное на 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();
    }
}

Вот и все! Просто и легко. Наслаждайтесь!

7 голосов
/ 08 декабря 2014

Я создал простую программу для создания переворачивания, например:

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

    }

}
4 голосов
/ 08 апреля 2016

Одним из лучших решений для переворачивания изображения без использования анимации ресурса является следующее: -

  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();
4 голосов
/ 31 января 2012

Учебник или ссылка на om252345 не дают правдоподобных 3D-сальто. Простое вращение по оси Y не то, что сделано в iOS. Эффект увеличения также необходим для создания этого приятного ощущения при перевороте. Для этого взгляните на этот пример . Здесь также есть видео .

3 голосов
/ 19 ноября 2016
  1. Самый простой способ сделать это - использовать ViewPropertyAnimator

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

    Используя свободный интерфейс, вы можете создавать более сложную и захватывающую анимацию.Например, вы можете включить аппаратное ускорение, просто вызвав метод Layer () (API 16).Подробнее здесь

  2. Если вы хотите выяснить, как создать трехмерную анимацию, пожалуйста, следуйте здесь и здесь

  3. Я реализовал собственное решение только для исследования.Он включает в себя: отмену, ускорение, поддержку API> = 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 был отменен, мы можем вычислить дельту и запустить обратную анимацию, используя текущую индексную анимацию и текущее значение времени воспроизведения..

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

Полный фрагмент кода вы можете найти здесь

1 голос
/ 15 мая 2019

Просто поместите вид, который вы собираетесь анимировать, вместо viewToFlip.

ObjectAnimator flip = ObjectAnimator.ofFloat(viewToFlip, "rotationY", 0f, 360f); // or rotationX
flip.setDuration(2000); // 2 seconds
flip.start();
0 голосов
/ 10 ноября 2018

Добавление к великому ответу А. Стинбергена. При переключении того же представления (например, при обновлении TextView) я удалил изменение View.Visibility в конструкторе, чтобы сделать переход более плавным.

public FlipListener(final View front, final View back) {
    this.mFrontView = front;
    this.mBackView = back;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...