Frage

Ich bin mit einem RotateAnimation ein Bild zu drehen, die ich als ein benutzerdefinierten zyklischen Spinner in Android bin mit. Hier ist meine rotate_indefinitely.xml-Datei, die ich in res/anim/ platziert:

<?xml version="1.0" encoding="UTF-8"?>
<rotate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="0"
    android:toDegrees="360"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatCount="infinite"
    android:duration="1200" />    

Als ich das meinen ImageView mit AndroidUtils.loadAnimation() anwenden, es funktioniert super!

spinner.startAnimation( 
    AnimationUtils.loadAnimation(activity, R.anim.rotate_indefinitely) );

Das einzige Problem ist, dass die Bilddrehung an der Spitze eines jeden Zyklus zu unterbrechen scheint.

Mit anderen Worten, das Bild um 360 Grad drehen, macht eine kurze Pause, dann um 360 Grad dreht wieder, etc.

Ich vermute, dass das Problem ist, dass die Animation eines Standard-Interpolator wie android:iterpolator="@android:anim/accelerate_interpolator" (AccelerateInterpolator) verwendet, aber ich weiß nicht, wie es zu sagen, nicht um die Animation zu interpolieren.

Wie kann ich Interpolation ausschalten (wenn das in der Tat das Problem ist), um meinen Animationszyklus reibungslos?

War es hilfreich?

Lösung

Sie haben Recht, über AccelerateInterpolator; Sie sollten LinearInterpolator stattdessen verwenden.

Sie können über das eingebaute in android.R.anim.linear_interpolator aus Ihrer Animation XML-Datei mit android:interpolator="@android:anim/linear_interpolator".

Oder Sie können Ihre eigene XML-Interpolation-Datei in Ihrem Projekt erstellen, zum Beispiel name it res/anim/linear_interpolator.xml:

<?xml version="1.0" encoding="utf-8"?>
<linearInterpolator xmlns:android="http://schemas.android.com/apk/res/android" />

Und fügen Sie zu Ihrer Animation XML:

android:interpolator="@anim/linear_interpolator"

Wichtiger Hinweis: Wenn Sie Ihre drehen Animation in einem Satz ist, der Interpolator Einstellung scheint nicht zu funktionieren. Machen Sie das Drehen das obere Element es fixiert. (Dies wird Ihre Zeit sparen.)

Andere Tipps

hatte ich dieses Problem auch und versuchte, den Linearinterpolators in xml ohne Erfolg zu setzen. Die Lösung, die für mich gearbeitet wurde die Animation als RotateAnimation in Code zu erstellen.

RotateAnimation rotate = new RotateAnimation(0, 180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotate.setDuration(5000);
rotate.setInterpolator(new LinearInterpolator());

ImageView image= (ImageView) findViewById(R.id.imageView);

image.startAnimation(rotate);

Dies funktioniert

<?xml version="1.0" encoding="UTF-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1600"
    android:fromDegrees="0"
    android:interpolator="@android:anim/linear_interpolator"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatCount="infinite"
    android:toDegrees="358" />

drehen Zum Umkehren:

<?xml version="1.0" encoding="UTF-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1600"
    android:fromDegrees="358"
    android:interpolator="@android:anim/linear_interpolator"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatCount="infinite"
    android:toDegrees="0" />

Vielleicht, so etwas wie dies helfen wird:

Runnable runnable = new Runnable() {
    @Override
    public void run() {
        imageView.animate().rotationBy(360).withEndAction(this).setDuration(3000).setInterpolator(new LinearInterpolator()).start();
    }
};

imageView.animate().rotationBy(360).withEndAction(runnable).setDuration(3000).setInterpolator(new LinearInterpolator()).start();

Durch die Art und Weise, können Sie drehen, indem mehr als 360 wie:

imageView.animate().rotationBy(10000)...
Versuchen

mit toDegrees="359" seit 360 ° und 0 ° gleich sind.

Bereinigen des <set>-Element, das das <rotate>-Element löst das Problem eingewickelt!

Dank Shalafi!

So Ihre Rotation_ccw.xml sollte wie folgt loook:

<?xml version="1.0" encoding="utf-8"?>

<rotate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="0"
    android:toDegrees="-360"
    android:pivotX="50%"
    android:pivotY="50%"
    android:duration="2000"
    android:fillAfter="false"
    android:startOffset="0"
    android:repeatCount="infinite"
    android:interpolator="@android:anim/linear_interpolator"
    />
ObjectAnimator.ofFloat(view, View.ROTATION, 0f, 360f).setDuration(300).start();

Versuchen Sie dies.

Egal, was ich versuchte, konnte ich das nicht bekommen Recht auf Arbeit mit dem Code (und setRotation) für eine gleichmäßige Rotation Animation. Was ich am Ende tat das Maß der Änderungen so klein ist, dass die kleinen Pausen nicht wahrnehmbar sind. Wenn Sie nicht zu viele Umdrehungen tun müssen, die Zeit, um diese Schleife auszuführen ist vernachlässigbar. Der Effekt ist eine sanfte Rotation:

        float lastDegree = 0.0f;
        float increment = 4.0f;
        long moveDuration = 10;
        for(int a = 0; a < 150; a++)
        {
            rAnim = new RotateAnimation(lastDegree, (increment * (float)a),  Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
            rAnim.setDuration(moveDuration);
            rAnim.setStartOffset(moveDuration * a);
            lastDegree = (increment * (float)a);
            ((AnimationSet) animation).addAnimation(rAnim);
        }

Als Hanry oben setzen Liner iterpolator erwähnt hat, ist in Ordnung. Aber wenn eine Drehung in einem Satz ist, müssen Sie android setzen. ShareInterpolator = „false“ es glatt zu machen

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
**android:shareInterpolator="false"**
>
<rotate
    android:interpolator="@android:anim/linear_interpolator"
    android:duration="300"
    android:fillAfter="true"
    android:repeatCount="10"
    android:repeatMode="restart"
    android:fromDegrees="0"
    android:toDegrees="360"
    android:pivotX="50%"
    android:pivotY="50%" />
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/linear_interpolator"
    android:duration="3000"
    android:fillAfter="true"
    android:pivotX="50%"
    android:pivotY="50%"
    android:fromXScale="1.0"
    android:fromYScale="1.0"
    android:toXScale="0"
    android:toYScale="0" />
</set>

Wenn Sharedinterpolator nicht falsch zu sein, der obige Code gibt Pannen.

Rotation Objekt programmatisch.

// Drehung im Uhrzeigersinn:

    public void rorate_Clockwise(View view) {
        ObjectAnimator rotate = ObjectAnimator.ofFloat(view, "rotation", 180f, 0f);
//        rotate.setRepeatCount(10);
        rotate.setDuration(500);
        rotate.start();
    }

// Linkslauf:

 public void rorate_AntiClockwise(View view) {
        ObjectAnimator rotate = ObjectAnimator.ofFloat(view, "rotation", 0f, 180f);
//        rotate.setRepeatCount(10);
        rotate.setDuration(500);
        rotate.start();
    } 

Ansicht ist Gegenstand Ihres Image oder anderer Widgets.

rotate.setRepeatCount (10);. Verwendung wiederholen Sie Ihre Rotation

500 ist Ihre Animation Zeitdauer.

Wenn Sie eine Set-Animation wie ich verwenden, sollten Sie die Interpolation innerhalb des eingestellten Tag hinzu:

<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/linear_interpolator">

 <rotate
    android:duration="5000"
    android:fromDegrees="0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatCount="infinite"
    android:startOffset="0"
    android:toDegrees="360" />

 <alpha
    android:duration="200"
    android:fromAlpha="0.7"
    android:repeatCount="infinite"
    android:repeatMode="reverse"
    android:toAlpha="1.0" />

</set>

Das ist für mich gearbeitet.

Ist es möglich, dass, weil Sie von 0 bis 360 gehen, Sie ein wenig mehr Zeit in 0/360 verbringen, als Sie erwarten? Vielleicht setzen toDegrees bis 359 oder 358.

In Android, wenn Sie ein Objekt animieren wollen und macht es ein Objekt aus location1 bewegen, um die Animation API Figuren aus den Zwischenstellen (Tweens) LOCATION2, und reiht dann auf den Hauptthread die entsprechenden Verschiebeoperationen zu den entsprechenden Zeiten mit Hilfe eines Timers. Dies funktioniert gut, außer dass der Haupt-Thread in der Regel für viele andere Dinge verwendet wird - Malerei, Dateien zu öffnen, reagiert auf Benutzereingaben usw. Ein anstehender Timer kann oft verzögert werden. Gut geschriebene Programme werden immer versuchen, so viele Operationen wie möglich im Hintergrund (Nicht-Haupt) Threads zu tun aber nicht immer vermeiden, kann den Haupt-Thread verwenden. Vorgänge, die Sie benötigen auf einem UI-Objekt arbeiten immer auf dem Hauptthread getan werden müssen. Außerdem werden viele APIs Operationen zurück zu dem Haupt-Thread als eine Form von fadenSicherheitsTrichter.

Ansichten alle auf dem gleichen GUI-Thread erstellt werden, die auch für alle Benutzer-Interaktion verwendet wird.

Wenn Sie also GUI schnell aktualisieren müssen oder wenn die Wiedergabe zu viel Zeit in Anspruch nimmt und Benutzer beeinflusst Erfahrung dann Surface verwenden.

Beispiel Dreh Bild:

public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {
    private DrawThread drawThread;

    public MySurfaceView(Context context) {
        super(context);
        getHolder().addCallback(this);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {   
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        drawThread = new DrawThread(getHolder(), getResources());
        drawThread.setRunning(true);
        drawThread.start();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        boolean retry = true;
        drawThread.setRunning(false);
        while (retry) {
            try {
                drawThread.join();
                retry = false;
            } catch (InterruptedException e) {
            }
        }
    }
}


class DrawThread extends Thread{
    private boolean runFlag = false;
    private SurfaceHolder surfaceHolder;
    private Bitmap picture;
    private Matrix matrix;
    private long prevTime;

    public DrawThread(SurfaceHolder surfaceHolder, Resources resources){
        this.surfaceHolder = surfaceHolder;

        picture = BitmapFactory.decodeResource(resources, R.drawable.icon);

        matrix = new Matrix();
        matrix.postScale(3.0f, 3.0f);
        matrix.postTranslate(100.0f, 100.0f);

        prevTime = System.currentTimeMillis();
    }

    public void setRunning(boolean run) {
        runFlag = run;
    }

    @Override
    public void run() {
        Canvas canvas;
        while (runFlag) {
            long now = System.currentTimeMillis();
            long elapsedTime = now - prevTime;
            if (elapsedTime > 30){

                prevTime = now;
                matrix.preRotate(2.0f, picture.getWidth() / 2, picture.getHeight() / 2);
            }
            canvas = null;
            try {
                canvas = surfaceHolder.lockCanvas(null);
                synchronized (surfaceHolder) {
                    canvas.drawColor(Color.BLACK);
                    canvas.drawBitmap(picture, matrix, null);
                }
            } 
            finally {
                if (canvas != null) {
                    surfaceHolder.unlockCanvasAndPost(canvas);
                }
            }
        }
    }
}

Aktivität:

public class SurfaceViewActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new MySurfaceView(this));
    }
}

Versuchen Sie, mehr als 360 zu verwenden, Neustarten zu vermeiden.

Ich verwende 3600 insted von 360 und das funktioniert gut für mich:

<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="0"
    android:toDegrees="3600"
    android:interpolator="@android:anim/linear_interpolator"
    android:repeatCount="infinite"
    android:duration="8000"
    android:pivotX="50%"
    android:pivotY="50%" />

In Kotlin:

 ivBall.setOnClickListener(View.OnClickListener {

            //Animate using XML
            // val rotateAnimation = AnimationUtils.loadAnimation(activity, R.anim.rotate_indefinitely)

            //OR using Code
            val rotateAnimation = RotateAnimation(
                    0f, 359f,
                    Animation.RELATIVE_TO_SELF, 0.5f,
                    Animation.RELATIVE_TO_SELF, 0.5f

            )
            rotateAnimation.duration = 300
            rotateAnimation.repeatCount = 2

            //Either way you can add Listener like this
            rotateAnimation.setAnimationListener(object : Animation.AnimationListener {

                override fun onAnimationStart(animation: Animation?) {
                }

                override fun onAnimationRepeat(animation: Animation?) {
                }

                override fun onAnimationEnd(animation: Animation?) {

                    val rand = Random()
                    val ballHit = rand.nextInt(50) + 1
                    Toast.makeText(context, "ballHit : " + ballHit, Toast.LENGTH_SHORT).show()
                }
            })

            ivBall.startAnimation(rotateAnimation)
        })
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top