10

Ich arbeite an animierten benutzerdefinierten Ansichten für meine Android-App. Ich habe dies über Property Animations erreicht und invalidate() auf der Ansicht in dem onAnimationUpdate() Rückruf Aufruf per https://developer.android.com/guide/topics/graphics/prop-animation.html:Animation zu Beginn der Aktivität springt

Je nachdem, welche Eigenschaft oder Objekt, das Sie animieren, müssen Sie möglicherweise die invalidate() -Methode auf einem Blick rufen Erzwingen, dass sich der Bildschirm mit den aktualisierten animierten Werten neu erstellt. Dies tun Sie im onAnimationUpdate() Callback.

Mein Problem ist, dass, wenn diese Animationen zu Beginn einer neu Aktivität gestartet ausgeführt werden, sie Frames am Anfang überspringen, wodurch sie sehr deutlich springen. Ich habe beide versucht:

  1. Starten der Animation sofort aus der onCreate() Methode Aktivitäten
  2. Starten der Animation auf dem OnGlobalLayout() Rückruf, um die ViewTreeObserver der Stammansicht Aktivitäten verwenden.

Ich tat letzteres, da ich dachte, dass die Animation möglicherweise aufgerufen wurde, bevor das Layout fertiggestellt wurde, aber das Ergebnis ist das gleiche.

Mit Logs habe ich festgestellt, dass der onAnimationUpdate() Callback während der gesamten Animation (dh alle 10-20 ms oder so, von Anfang bis Ende) konsistent aufgerufen wird. onAnimationUpdate() ruft einfach invalidate() an, was die View zwingen sollte, sich neu zu zeichnen, idealerweise sofort (aber die Dokumentation behauptet nur, dass dies "irgendwann in der Zukunft" passiert). Das scheint genau das Problem zu sein: onDraw() wird nur einmal oder zweimal am Anfang aufgerufen, bevor es nicht für ca. 250 ms aufgerufen wird. Danach wird es alle 10-20 ms aufgerufen, wie es die ganze Zeit haben sollte. Aber dieser Zeitblock verursacht eine merkliche Verzögerung in der Animation.

Um klar zu sein, dieses Problem tritt nur zu Beginn der Aktivität auf. Wenn ich vor dem Start der Animation einfach eine Verzögerung von 300 ms einstelle, läuft sie reibungslos durch. Aber ich mag diese Lösung nicht, da es hacky ist. Es scheint das Problem ist, dass onDraw() nicht sofort invalidate() in der Nähe des Beginns der Aktivität aufgerufen wird. Aber ich kann nicht herausfinden, warum das ist, was blockiert onDraw(), oder wie man es überhaupt reparieren kann.

Ich fand nur dieses StackOverFlow-Thread: Animation at the beginning of activity skips frames, wo das Plakat die identische Problem hat. Der Basiscode ist da und die Videos verdeutlichen das Problem. Ich kann meinen Code auch posten, aber ich denke, dass die Tatsache, dass das Problem in der einfachsten Test-App auftaucht, zeigt, dass da noch etwas anderes vor sich geht.

Antwort

5

Da keine Codes angehängt sind, nehme ich an, dass Sie eine Übergangsanimation für die Aktivität haben. Wenn dies der Fall ist, kann dies das Problem verursachen. Da zwei Animationen gleichzeitig ausgeführt werden. Deaktivieren Sie den Übergang und versuchen Sie es.

startActivity(intent); 
getActivity().overridePendingTransition(0, 0); 
+1

Ich hatte keine benutzerdefinierte Übergangsanimation, aber standardmäßig ist eine aktiviert. Das Deaktivieren der Übergangsanimation wie vorgeschlagen hat die Animation tatsächlich repariert. Da dies jedoch störend ist, habe ich den folgenden Aktivitätsrückruf gefunden: [onEnterAnimationComplete()] (https://developer.android.com/reference/android/app/Activity.html#onEnterAnimationComplete()). Das Problem wird dort offiziell erklärt: "Aktivitäten können während des Zeitraums, in dem ihre Fenster animiert werden, nicht zeichnen." Das Starten meiner Animationen von diesem Rückruf behebt das Problem. – asaini007

+0

@ asaini007 Die Methode ist da, aber ... nur über API 21 verfügbar. Übrigens, es funktioniert nicht die ganze Zeit. –

2

Es klingt wie Ihre Draw-Schleife UI-Thread wird verhungert.

Ich würde TraceView verwenden, um sicher zu sein, dass es keine Methoden gibt, die Ihre Zeichenaufrufe blockieren.http://tools.android.com/tips/traceview

Dies sollte Ihnen helfen zu bestimmen, was anstelle der OnDraw-Methode aufgerufen wird.