web-dev-qa-db-de.com

Erstellen einer 3D-Flip-Animation in Android mithilfe von XML

Ich habe ein 3D-Flip einer Ansicht mit diesem Android-Tutorial .__ erstellt. Allerdings habe ich es programmgesteuert gemacht und ich möchte, falls möglich, alles in XML machen. Ich spreche nicht davon, den Blick auf die Mitte zu verkleinern und wieder herauszuziehen, sondern einen echten 3D-Flip. 

Ist das über XML möglich?

23

Hier ist die Antwort, obwohl es nur mit 3.0 und höher funktioniert. 

1) Erstellen Sie einen neuen Ressourcenordner mit dem Namen "Animator".

2) Erstellen Sie eine neue .xml-Datei, die ich "flipping" nennen werde. Verwenden Sie den folgenden 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>

Nein, die objectAnimator-Tags beginnen nicht mit einem Großbuchstaben "O".

3) Starten Sie die Animation mit folgendem 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();

Ich habe das alles von hier bekommen.

55

Da die Antworten auf diese Frage ziemlich veraltet sind, folgt hier eine modernere Lösung, die auf ValueAnimators basiert .. Diese Lösung implementiert einen echten, visuell ansprechenden 3D-Flip, da er nicht nur die Ansicht umkehrt, sondern auch skaliert Spiegeln (so macht Apple es).

Zuerst richten wir den ValueAnimator ein:

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

Und der entsprechende 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);
    }
}

Das ist es!

Nach diesem Setup können Sie die Ansichten durch Aufruf umkehren

mFlipAnimator.start();

und kehren Sie den Flip um, indem Sie anrufen

mFlipAnimator.reverse();

Wenn Sie prüfen möchten, ob die Ansicht umgedreht ist, implementieren Sie diese Funktion und rufen Sie sie auf:

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

Sie können auch überprüfen, ob die Ansicht derzeit umkehrt, indem Sie diese Methode implementieren:

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

Sie können die obigen Funktionen kombinieren, um eine Nice-Funktion zu implementieren, um die Umkehrung umzuschalten, je nachdem, ob sie umgedreht ist oder nicht:

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

Das ist es! Simpel und einfach. Genießen!

22
A. Steenbergen

Ich habe ein einfaches Programm zum Erstellen von Spiegeln erstellt:

enter image description here

In Activity müssen Sie diese Methode erstellen, um flip_rotation zur Ansicht hinzuzufügen.

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

dazu müssen Sie die Hauptklasse kopieren, die für die Bereitstellung von flip_rotation verwendet wird.

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

    }

}
7
Tushar Pandey

Eine der besten Lösungen, um das Bild ohne Verwendung der Ressourcenanimation umzudrehen, lautet wie folgt:

  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

Das Tutorial oder der Link von om252345 erzeugen keine glaubwürdigen 3D-Flips. Eine einfache Drehung auf der Y-Achse ist nicht das, was in iOS gemacht wird. Der Zoomeffekt wird auch benötigt, um das Nice-Flip-Feeling zu erzeugen. Sehen Sie sich dazu dieses Beispiel ..__ an. Es gibt auch ein Video hier .

4
Ephraim
  1. Am einfachsten geht es mit ViewPropertyAnimator .

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

    Mit der fließenden Benutzeroberfläche können Sie komplexere und aufregendere Animationen erstellen. Sie können die Hardwarebeschleunigung aktivieren, indem Sie einfach mit der Layer () -Methode (API 16) aufrufen. Mehr hier

  2. Wenn Sie herausfinden möchten, wie Sie eine 3D-Animation erstellen, folgen Sie hier und hier .

  3. Ich habe meine eigene Lösung nur für eine Recherche eingeführt. Es beinhaltet: Abbruch, Beschleunigung, Support API> = 15 und basiert auf Property Animation . Die gesamte Animation enthält 4 Teile, 2 für jede Seite. Jeder objectAnimator hat einen Listener, der den aktuellen Animationsindex definiert und ein Bild im onAnimationStart und den aktuellen Wert für die Wiedergabezeit im onAnimationCancel ..__ darstellt

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

    Zum Einrichten eines Anrufs

    mAnimatorSet.play(mQuarterAnim1).before(mQuarterAnim2)
    

    Wenn AnimatorSet abgebrochen wurde, können wir das Delta berechnen und die umgekehrte Animation ausführen, wobei die aktuelle Indexanimation und der aktuelle Wert für die Wiedergabezeit zugrunde liegen.

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

    vollständiges Beispiel hier

3
yoAlex5

Platzieren Sie einfach die Ansicht, die Sie animieren möchten, anstelle von viewToFlip.

ObjectAnimator flip = ObjectAnimator.ofFloat(viewToFlip, "rotationY", 0f, 360f); // or rotationX
flip.setDuration(2000); // 2 seconds
flip.start();
1
Alireza Noorali

Die wunderbare Antwort von A. Steenbergen. Wenn ich dieselbe Ansicht umblättere (beispielsweise eine Variable TextView), habe ich die View.Visibility-Änderung im Konstruktor entfernt, um den Übergang reibungsloser zu gestalten.

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