Il semble que les anciennes animations de vue (translate
, scale
, etc.) ne sont plus acceptées par le AnimationInflater
, au moins comme pour ICS. J'ai lu son code dans 4.0.4, et il n'attend explicitement que les éléments XML set
, objectAnimator
, animator
.
Même si la documentation sur http://developer.Android.com/guide/topics/resources/animation-resource.html continue d'inclure les animations de vue, elles semblent obsolètes. Essayer de les utiliser entraîne, par exemple, l'erreur Java.lang.RuntimeException: Unknown animator name: translate
.
En tant que tel, il devient nécessaire d'utiliser le ObjectAnimator
d'Android. Cependant, il n'accepte pas les valeurs fractionnaires de la dimension associée de lui-même ou de son parent (largeur pour translationX
, par exemple) comme les anciennes animations de vue le faisaient sous la forme "75%p"
.
Construire le ObjectAnimator
manuellement au moment de l'exécution, en récupérant par programme la taille du fragment, n'est pas possible car le FragmentTransaction
n'accepte que les animations déclaratives spécifiées par un résid.
Mon objectif est de traduire hors écran un fragment qui remplit une activité entière (je fais essentiellement une transition entre deux fragments). Il s'agit de l'implémentation existante de TranslationAnimation
(slide_in_right.xml
, qui avec son homologue slide_out_left.xml
n'est pas exposé pour une raison quelconque dans Android.R.anim
, et je dois donc les dupliquer dans ma base de code):
<set xmlns:Android="http://schemas.Android.com/apk/res/Android">
<translate
Android:fromXDelta="100%p"
Android:toXDelta="0"
Android:duration="@Android:integer/config_mediumAnimTime"/>
</set>
Mon niveau d'API est défini sur 14.
Merci!
En fait, les animateurs d'objets acceptent des valeurs fractionnaires. Mais peut-être n'avez-vous pas compris le concept sous-jacent d'un objectAnimator ou plus généralement d'un animateur de valeur. Un animateur de valeurs animera une valeur liée à une propriété (telle qu'une couleur, une position à l'écran (X, Y), un paramètre alpha ou tout ce que vous voulez). Pour créer une telle propriété (dans votre cas xFraction et yFraction), vous devez créer vos propres getters et setters associés à ce nom de propriété. Disons que vous souhaitez traduire un FrameLayout de 0% à 25% de la taille de votre écran entier. Ensuite, vous devez créer une vue personnalisée qui encapsule les objets FrameLayout et écrire vos getters et setters.
public class SlidingFrameLayout extends FrameLayout
{
private static final String TAG = SlidingFrameLayout.class.getName();
public SlidingFrameLayout(Context context) {
super(context);
}
public SlidingFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public float getXFraction()
{
int width = getWindowManager().getDefaultDisplay().getWidth();
return (width == 0) ? 0 : getX() / (float) width;
}
public void setXFraction(float xFraction) {
int width = getWindowManager().getDefaultDisplay().getWidth();
setX((width > 0) ? (xFraction * width) : 0);
}
}
Ensuite, vous pouvez utiliser la méthode xml pour déclarer l'animateur d'objet en plaçant xFraction sous l'attribut xml de propriété et le gonfler avec un AnimatorInflater
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:propertyName="xFraction"
Android:valueType="floatType"
Android:valueFrom="0"
Android:valueTo="0.25"
Android:duration="500"/>
ou vous pouvez simplement utiliser le code de ligne Java
ObjectAnimator oa = ObjectAnimator.ofFloat(menuFragmentContainer, "xFraction", 0, 0.25f);
J'espère que cela vous aide!
Olivier,
L'implémentation du SDK Android de FragmentTransaction
attend un Animator
tandis que, pour une raison obscure, l'implémentation de la bibliothèque de support attend un Animation
, si vous utilisez l'implémentation de fragment de la bibliothèque de support, votre animation de traduction sera travail
Voici un important gotcha pour ceux qui essaient de créer des animations de vue comme translate
et scale
.
Les animations des propriétés sont situées dans un répertoire nommé "animateur": res/animator/filename.xml
MAIS, les animations de vue doivent être placées dans un répertoire simplement appelé "anim": res/anim/filename.xml
J'ai d'abord mis mon animation de vue dans un dossier "animateur", et j'étais confus à propos de Android Studio se plaignant du fait que la traduction n'était pas un élément valide. Donc, NO , les animations de vue ne sont pas obsolètes. Elles ont juste leur propre emplacement pour une raison déroutante.
voici un exemple de travail complet (œuvres décrites par l'auteur de la réponse acceptée.)
Appuyez sur le bouton pour basculer entre 2 fragments A et B (par animation de diapositives de droite à gauche). Les fragments sont juste du texte stupide (AAAAAA et BBBBB) avec des arrière-plans différents.
MainActivity.Java
package com.example.slidetrans;
import Android.app.Activity;
import Android.app.Fragment;
import Android.app.FragmentManager;
import Android.app.FragmentTransaction;
import Android.os.Bundle;
import Android.util.Log;
import Android.view.View;
import Android.view.View.OnClickListener;
import Android.widget.Button;
public class MainActivity extends Activity {
private static final String TAG = "Main";
boolean showingA = true;
Button button;
A a;
B b;
private void incarnate(FragmentManager fm){
int layoutId = R.id.frame;
boolean fragmentWasNull = false;
Fragment f = fm.findFragmentById(layoutId);
if (f == null){
Log.i(TAG, "fragment is null");
if (showingA){
f = a = new A();
} else {
f = b = new B();
}
fragmentWasNull = true;
} else {
Log.i(TAG, "fragment is not null");
showingA = (f instanceof A);
updateButtonText();
}
if (fragmentWasNull){
FragmentTransaction ft = fm.beginTransaction();
ft.add(layoutId, showingA ? a : b, "main").commit();
}
}
private void updateButtonText(){
button.setText(showingA ? "slide in B" : "slide in A");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
FragmentManager fm = getFragmentManager();
button = (Button)findViewById(R.id.button);
incarnate(fm);
OnClickListener listener = new OnClickListener() {
@Override
public void onClick(View v) {
FragmentManager fm = getFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.setCustomAnimations(R.anim.in, R.anim.out);
transaction.replace(R.id.frame, showingA ? new B() : new A()).commit();
showingA = !showingA;
updateButtonText();
}
};
button.setOnClickListener(listener);
}
}
LL.Java
package com.example.slidetrans;
import Android.content.Context;
import Android.util.AttributeSet;
import Android.widget.LinearLayout;
public class LL extends LinearLayout {
public LL(Context context) {
super(context);
}
public LL(Context context, AttributeSet attrs) {
super(context, attrs);
}
public float getXFraction() {
final int width = getWidth();
if (width != 0) return getX() / getWidth();
else return getX();
}
public void setXFraction(float xFraction) {
final int width = getWidth();
float newWidth = (width > 0) ? (xFraction * width) : -9999;
setX(newWidth);
}
}
main.xml (mise en page)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:orientation="vertical"
>
<Button
Android:id="@+id/button"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:text="slide in B" />
<FrameLayout
Android:id="@+id/frame"
Android:layout_width="match_parent"
Android:layout_height="match_parent" >
</FrameLayout>
</LinearLayout>
a.xml (mise en page)
<?xml version="1.0" encoding="utf-8"?>
<com.example.slidetrans.LL xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:orientation="vertical"
Android:background="#00FF00"
>
<TextView
Android:id="@+id/aText"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:text="AAAAAAAAAAAAAAAAAA"
Android:textSize="30sp"
Android:textStyle="bold"
/>
</com.example.slidetrans.LL>
b.xml (mise en page)
<?xml version="1.0" encoding="utf-8"?>
<com.example.slidetrans.LL xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:orientation="vertical"
Android:background="#FFFF00"
>
<TextView
Android:id="@+id/bText"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:textSize="30sp"
Android:textStyle="bold"
Android:text="BBBBBBBBBB"
/>
</com.example.slidetrans.LL>
in.xml (anim)
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:Android="http://schemas.Android.com/apk/res/Android">
<objectAnimator
Android:duration="500"
Android:interpolator="@Android:anim/linear_interpolator"
Android:propertyName="xFraction"
Android:valueFrom="1.0"
Android:valueTo="0.0"
Android:valueType="floatType" />
</set>
out.xml (anim)
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:Android="http://schemas.Android.com/apk/res/Android">
<objectAnimator
Android:duration="500"
Android:interpolator="@Android:anim/linear_interpolator"
Android:propertyName="xFraction"
Android:valueFrom="0.0"
Android:valueTo="-1.0"
Android:valueType="floatType" />
</set>
Les animations de vue ne sont pas obsolètes. Si vous utilisez Eclipse, vous pouvez les trouver sous une animation d'interpolation comme type de ressource lors de la création d'un nouveau fichier XML Android Android.