1) In Bezug auf die Prämie:
Existing answers on SO schlagen die FrameLayout Subklassen ...
Wenn Sie eine ObjectAnimator
verwenden möchten, müssen Sie keine andere Wahl, als die View
Sie animieren möchten, Unterklasse . Sie müssen die ObjectAnimator
mit den notwendigen Getter und Setter-Methoden zur Verfügung stellen, um seine Magie zu tun, da es im Wesentlichen nur diese Getter-und Setter-Methoden aufrufen, um die Animation
durchzuführen.
Die Frage, die Sie verknüpfen zu (Animate the transition between fragments) FrameLayout
ist Subklassen eine setXFraction()
und eine getXFraction()
Methode hinzuzufügen. Sie sind so implementiert, dass der x-Wert relativ zur Breite des FrameLayout
festgelegt wird. Nur dadurch kann die ObjectAnimator
alles andere als zwischen absoluten Werten animieren.
Zusammengefasst, die ObjectAnimator
selbst nicht wirklich viel Animation, ruft nur Getter und Setter-Methoden durch Reflexion.
Gibt es wirklich keine Möglichkeit, die tatsächlichen Bildschirmpixelabmessungen (nicht nur dp) in die XML-Datei zu bekommen?
Mit einem ObjectAnimator
gibt es keine Möglichkeit, das zu erreichen. ObjectAnimators
nur interpolieren von einem Startwert zu und Endwert. Wie ich oben erklärt habe, definiert die Setter-Methode, was tatsächlich passiert.
zum Beispiel eine benutzerdefinierte Funktion aufrufen, die die Breite feinen wäre zurückkehrt, oder definieren eine Konstante, die Code festlegen, Codesatz mit dem Konstante, die die Bildschirmbreite gleich ist, dann, dass konstanten Zugriff von der XML wäre genauso nützlich.
Sie können keinen Wert aus Code in eine XML-Ressource einfügen. Alles, was in Ihren XML-Dateien enthalten ist, wird in Ihr APK kompiliert, wenn Sie es erstellen, und kann zur Laufzeit nicht geändert werden. Und das ist auch eine Antwort auf Ihre andere Frage: Es gibt keine Ressource oder Konstante oder irgendetwas, auf das in XML zugegriffen werden könnte, das die aktuelle Bildschirmgröße enthält. Dynamische Werte wie die Bildschirmgröße des Geräts, auf dem die App installiert ist, können nicht Teil dieser Ressourcen sein, da alles in ihnen beim Erstellen in Ihre App kompiliert wird.
2) Mögliche Lösung: Ansicht Animationen
Eine mögliche Lösung ist Animationen Ansicht anstelle eines ObjectAnimator
zu verwenden. Mit Blick auf Animationen können Sie Brüche statt nur absolute Werte angeben:
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromYDelta="-100%" android:toYDelta="0%" android:duration="1000"/>
</set>
Dieses eine View
von -100%
zu 0%
der Bildschirmhöhe animieren würde. Mit anderen Worten von komplett vom Bildschirm bis zur Position View
. Sie können es wie folgt verwenden:
Animation animation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.slide_down);
view.startAnimation(animation);
Ich weiß, dass dies keine Hilfe für Sie sein kann. Es gibt Fälle, in denen man ObjectAnimators
verwenden muss und keine Ansichtsanimationen verwenden kann. Aber solange Sie View-Animationen verwenden können, sollte dies Ihr Problem lösen.
3) Best practice
Was wir wirklich hier Adressierung werden sollte, ist, was ich denke, eine falsche Vorstellung von Ihrer Seite ist. Wie Sie bereits bemerkt haben, hat jede Animation, die Sie in XML definieren, absolute Start- und Endwerte. Diese Werte sind statisch und können nach dem Erstellen der App nicht geändert werden.
Wenn man sich anschaut, wie die Ressourcen arbeiten mit den vielen verfügbaren Selektoren und auch mit dp, sp ... dann werden Sie erkennen, dass es ausgelegt ist, eine Sache zu tun:
können Sie zum Beispiel eine Animation definieren, die bewegt a View
von 100dp. Dp ist eine Messung der physikalischen Größe, 100dp ist die exakt gleiche physikalische Größe eines beliebigen Bildschirms mit beliebiger Pixeldichte. Mithilfe von Selektoren können Sie diese Animation für Geräte mit kleineren oder größeren Bildschirmen ändern, bei denen die Animation möglicherweise die View
zu viel oder zu wenig bewegt. Sie können jedoch nur statische Werte eingeben. Abgesehen von der Arbeit mit Selektoren können Sie die Animation nicht für jedes Gerät anpassen.
Sie sehen also, die Ressourcen sind wirklich nur für alles entwickelt, was statisch und unveränderlich ist. Es funktioniert hervorragend für Dimensionen oder String-Übersetzungen, aber manchmal mit Animationen kann es ein bisschen Schmerz sein.Wie ich oben sagte, bieten nur View-Animationen eine Möglichkeit, die statische Natur zu umgehen, indem sie die Möglichkeit bieten, Brüche anstelle von absoluten Werten zu spezifizieren. Aber im Allgemeinen können Sie nichts Dynamisches in XML definieren.
Um dieses Argument Blick auf Googles ausgezeichnete DevBytes Videos über Animation futher erhärten:
Dann werden Sie feststellen, dass in diesen Beispielen keine einzige Animation in xml definiert ist. Sicher könnte man argumentieren, dass sie sie nicht in xml definieren, weil sie es einfacher haben wollen, den Code zu erklären und zu zeigen, aber das ist meiner Meinung nach ein weiterer Punkt:
Sie können eine Animation nicht statisch definieren Ressourcen, die von einem rein dynamischen Wert abhängen
Da die Bildschirmbreite/-höhe von Gerät zu Gerät unterschiedlich ist, benötigen Sie für jedes Gerät unterschiedliche Animationen. Nur Ansichtsanimationen bieten eine Möglichkeit, Brüche anstelle von absoluten Werten zu definieren. In jedem anderen Fall müssen Sie die Animationen programmgesteuert definieren. Zum Glück ist das nicht schwierig, mit ObjectAnimators
:
Animator animator = ObjectAnimator.ofFloat(view, View.X, startValue, endValue);
animator.start();
Dies würde die x-Position der View
vom Anfang bis zum Ende Wert in Pixel animiert. Sie können in der Breite der View
passieren sie zu animieren, wie Sie wollen:
Animator animator = ObjectAnimator.ofFloat(view, View.X, -view.getWidth(), 0.0f);
animator.start();
Dies würde die View
animiert von der linken Seite zu schieben. Es beginnt komplett außerhalb des Bildschirms und stoppt in seiner endgültigen Position. Sie könnten auch dies nur tun:
view.animate().x(targetValue);
Das die View
von seiner aktuellen x-Position auf den Ziel x Wert animieren würde.
Aber bitte missverstehen Sie mich nicht, Sie sollten immer noch versuchen, so viel wie möglich zu definieren - sei es Animationen oder irgendetwas anderes - in den Ressourcen. Hardcoding-Animationen oder andere Werte sollten so weit wie möglich vermieden werden, es sei denn, es ist wie in Ihrem Fall notwendig.
4) Zusammenfassung
Um es zusammenzufassen:
- Sie können nicht tun, was Sie mit
ObjectAnimators
tun wollen, ohne die Getter und Setter-Methoden hinzufügen, die Sie brauchen, um die View
Sie wollen animieren .
- Wenn möglich, verwenden Sie view animations. Mit ihnen können Sie Animationen basierend auf Bruchteilen der Breite oder Höhe des
View
definieren.
- Wenn das obige nicht funktioniert oder nicht auf Ihre Situation anwendbar ist, dann definieren Sie die Animationen programmatically, dies wird in jedem Fall funktionieren.
Ich hoffe, ich konnte Ihnen helfen und wenn Sie weitere Fragen haben, zögern Sie nicht zu fragen!
Danke für die tolle Antwort. Ich schätze, die große Einschränkung ist, dass die einzige Möglichkeit, einer FragmentTransaction eine Animation hinzuzufügen, in setCustomAnimations (int enter, int exit) besteht. Und diese API scheint eine Animator-Ressourcen-ID und keine Animations-Ressourcen-ID zu erwarten. Das Definieren meines Animators im Code ist kein Problem. Aber kann ich ihm dann eine Ressourcen-ID geben? –
OK, Problem gelöst, ich erstelle meinen Code-Animator in der onCreateAnimator-Methode des Fragments. –
Ich wollte dir jetzt gerade von 'onCreateAnimator() 'erzählen, rate mal, du hast es selbst herausgefunden. Es freut mich, dass ich helfen konnte! –