animations android animation

animations - android object animator



Android: utilizando ObjectAnimator para traducir una vista con valores fraccionarios de la dimensiĆ³n de la vista (5)

Aquí hay un mensaje importante para aquellos que intentan crear animaciones de vista como translate y scale .

Las animaciones de propiedades se encuentran en un directorio llamado " animator ": res/animator/filename.xml

PERO, las animaciones de vista deben colocarse en un directorio llamado simplemente " anim ": res/anim/filename.xml

Primero coloqué la animación de mi vista en una carpeta "animator" y me confundí acerca de que Android Studio se quejaba de que la traducción no era un elemento válido. Entonces, NO , las animaciones de vista no están en desuso. Simplemente tienen su propia ubicación por alguna razón confusa.

Parece que las animaciones de vistas antiguas ( translate , scale , etc.) ya no son aceptadas por AnimationInflater , al menos desde ICS. Leí su código en 4.0.4, y espera explícitamente solo los elementos XML set , objectAnimator , animator .

Aunque la documentación en http://developer.android.com/guide/topics/resources/animation-resource.html continúa incluyendo las animaciones de la vista, parecen estar en desuso. Intentar utilizarlos da como resultado, por ejemplo, el error java.lang.RuntimeException: Unknown animator name: translate .

Como tal, se hace necesario usar el ObjectAnimator de Android. Sin embargo, no acepta valores fraccionarios de la dimensión asociada de sí misma o su elemento principal (ancho para la translationX , por ejemplo) como las antiguas animaciones de vista lo hicieron en la forma "75%p" .

La construcción manual del ObjectAnimator en tiempo de ejecución, mediante la ObjectAnimator del tamaño del Fragment mediante programación, no es posible porque FragmentTransaction solo acepta las animaciones declarativas especificadas por un resid.

Mi objetivo es traducir fuera de pantalla un Fragmento que está llenando una Actividad completa (básicamente estoy haciendo una transición de cambio entre dos fragmentos). Esta es la implementación de TranslationAnimation existente ( slide_in_right.xml , que junto con su contraparte slide_out_left.xml es por alguna razón no expuesta en android.R.anim , y por lo tanto tengo que duplicarlas en mi base de código):

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

Mi nivel de API está establecido en 14.

¡Gracias!


En realidad, los animadores de objeto aceptan valores fraccionarios. Pero tal vez no entendiste el concepto subyacente de un ObjectAnimator o, más en general, un animador de valor. Un animador de valores animará un valor relacionado con una propiedad (como un color, una posición en la pantalla (X, Y), un parámetro alfa o lo que quieras). Para crear dicha propiedad (en su caso xFraction e yFraction) necesita construir sus propios getters y setters asociados a este nombre de propiedad. Digamos que quieres traducir un FrameLayout de 0% a 25% del tamaño de toda tu pantalla. Luego, debe crear una vista personalizada que ajuste los objetos FrameLayout y escriba sus captadores y decodificadores.

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

Luego, puede usar la forma xml para declarar el animador de objetos poniendo xFraction bajo el atributo property xml e inflarlo con 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"/>

o simplemente puedes usar el código de la línea java

ObjectAnimator oa = ObjectAnimator.ofFloat(menuFragmentContainer, "xFraction", 0, 0.25f);

Espero que te ayude!

Olivier,


La implementación de Android SDK de FragmentTransaction espera un Animator mientras, por alguna razón oscura, la implementación de la biblioteca de soporte espera una Animation , si usas la implementación de Fragment desde la biblioteca de soporte, tu animación de traducción funcionará


Las animaciones de vista no están en desuso. Si está utilizando Eclipse, puede encontrarlos en animación Tween como un tipo de recurso al crear un nuevo archivo XML de Android.


aquí está el ejemplo completo de trabajo (funciona según lo delineado por el autor de la respuesta aceptada).

Al presionar el botón, se alterna entre 2 fragmentos A y B (mediante la animación de diapositivas de derecha a izquierda). Los fragmentos son solo texto estúpido (AAAAAA y BBBBB) con diferentes antecedentes.

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 (diseño)

<?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 (diseño)

<?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 (diseño)

<?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>