Android – Hacer traducciones y objectAnimator en el mismo archivo XML
He estado tratando de hacer un efecto de rotación 3D Cube mientras se desliza de un fragmento a otro. Primero estaba usando un efecto de traducción (en XML) llamando con FragmentTransaction.setCustomAnimations(...)
y luego, al abrir / cerrar el fragmento, estaba jugando con la clase Camera para hacer la rotación.
Esto funcionaba bien, pero parece que también tengo (no me preguntes por qué) usar toda esta animación usando sólo un archivo XML. Después de una larga búsqueda descubrí que debería usar objectAnimator para hacer la rotación.
- No se encontró ninguna vista para id - DialogFragment + Fragment
- La biblioteca de la barra de acciones de AppCompat no muestra fragmentos añadidos
- Ciclo de vida del fragmento - ¿Qué método se llama mostrar / ocultar?
- FragmentManager.getFragmens (). Size () no disminuyen después de FragmentTransaction.remove (Fragment)
- ViewPager dentro de Fragmento desaparece después de transaction.remove () (Mantener instancia?)
Seguido de la muestra de Google y me las arreglo para hacer la animación de voltear. Ahora necesito traducir los fragmentos haciéndolos deslizarse adentro y deslizar hacia fuera. Parece que no puedo utilizar objectAnimator y traducir efecto en el mismo archivo XML. Dado que este error aparece:
java.lang.RuntimeException: Unknown animator name: translate at (...)
¿Alguna idea sobre cómo puedo hacer el efecto deslizante y usar el objectAnimator al mismo tiempo?
¡Gracias por tu tiempo!
Código que he estado usando:
Card_flip_right_in.xml
<set xmlns:android="http://schemas.android.com/apk/res/android" > <!-- Before rotating, immediately set the alpha to 0. --> <objectAnimator android:duration="0" android:propertyName="alpha" android:valueFrom="1.0" android:valueTo="0.0" /> <!-- Rotate. --> <objectAnimator android:duration="@integer/card_flip_time_full" android:interpolator="@android:interpolator/accelerate_decelerate" android:propertyName="rotationY" android:valueFrom="180" android:valueTo="0" /> <!-- Half-way through the rotation (see startOffset), set the alpha to 1. --> <objectAnimator android:duration="1" android:propertyName="alpha" android:startOffset="@integer/card_flip_time_half" android:valueFrom="0.0" android:valueTo="1.0" /> </set>
Fragmento llamando a otro fragmento: (la rotación del cubo debe ser visible entre este 2)
private void launchArticle(int prev, int pos){ ArticleFragment newFragment = new ArticleFragment(); Bundle args = new Bundle(); args.putString("pos", pos); args.putInt("prev", prev); newFragment.setArguments(args); android.app.FragmentTransaction transaction = getFragmentManager().beginTransaction(); Fragment currFrag = (Fragment)getFragmentManager().findFragmentById(R.id.headlines_fragment); if (currFrag != null) { transaction.hide(currFrag); } transaction.setCustomAnimations( R.animator.card_flip_right_in, R.animator.card_flip_right_out, R.animator.card_flip_left_in, R.animator.card_flip_left_out ); transaction.replace(R.id.fragment_container, newFragment, pos); transaction.addToBackStack(null); transaction.commit(); }
ACTUALIZAR:
He logrado resolver el problema anterior usando una clase que extiende mi framelayout de los fragmentos que estoy usando
SlidingFrameLayout.java
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() { final int width = getWidth(); if(width != 0) return getX() / getWidth(); else return getX(); } public void setXFraction(float xFraction) { final int width = getWidth(); setX((width > 0) ? (xFraction * width) : -9999); } public float getYFraction() { final int height = getHeight(); if(height != 0) return getY() / getHeight(); else return getY(); } public void setYFraction(float yFraction) { final int height = getHeight(); setY((height > 0) ? (yFraction * height) : -9999); } }
Y añadiendo esto a la objectAnimator:
<!-- Move --> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="@integer/card_flip_time_full" android:interpolator="@android:anim/linear_interpolator" android:propertyName="xFraction" android:valueFrom="-1" android:valueTo="0" />
Esto está funcionando mejor, pero los ejes de rotación están en el medio del FrameLayout y no está haciendo la ilusión de un cubo … ¿Es posible establecer los ejes de rotación en un cierto punto?
- ¿Cómo reemplazar el fragmento C con el fragmento A cuando se pulsa el botón Atrás?
- FragmentTransaction.replace reemplaza sólo el primer Fragment en un contenedor
- Android TextInputLayouts perder texto / contenido al volver en la transacción de fragmentos
- Cómo borrar backStack de soporte FragmentManager?
- Cómo mostrar el fragmento de entrada sobre el fragmento de salida mientras se anima.
- Mover fragmento de Android a un contenedor diferente No se puede cambiar el identificador de contenedor de fragmento
- Cambiar el orden z de Fragmentos durante la FragmentTransaction en curso
- Congelación de la interfaz de usuario cuando la transacción de fragmentos
Solucionado el problema creando mis propios métodos en el FrameLayout extendido. Aquí está el código del FrameLayout extendido:
//Rotate from Left to Right turning visible public float getRotateLeftRightIn(){ return getRotationY(); } public void setRotateLeftRightIn(int rotateLeftRightIn){ setPivotX(getWidth()); setPivotY(getHeight()/2); setRotationY(rotateLeftRightIn); }
Y en el XML:
<!-- Rotate. --> <objectAnimator android:duration="@integer/card_flip_time_full" android:interpolator="@android:interpolator/accelerate_decelerate" android:propertyName="rotateLeftRightIn" android:valueFrom="@integer/card_flip_rotation_off" android:valueTo="0" android:valueType="intType"/>
En este caso, @integer/card_flip_time_full
representa la duración de toda la animación y @integer/card_flip_rotation_off
representa los grados (en este caso -90%).
Después de esto, todo lo que necesito hacer para que esta animación funcione es, al iniciar el fragmento, establecer los archivos xml en la animación personalizada
transaction.setCustomAnimations(enter,exit,popEnter,popExit);
Espero que esto puede ser útil para alguien ^ ^
Una alternativa a la respuesta aceptada, se podría definir un conjunto de animación, como se ve aquí:
<item android:state_pressed="true"> <set> <objectAnimator android:propertyName="translationZ" android:duration="100" android:valueTo="2" android:valueType="floatType"/> <!-- you could have other objectAnimator elements here for "x" and "y", or other properties --> </set> </item> <item android:state_enabled="true" android:state_pressed="false" android:state_focused="true"> <set> <objectAnimator android:propertyName="translationZ" android:duration="100" android:valueTo="2" android:valueType="floatType"/> </set> </item>
¿Cómo usar StateListAnimator?
- Manera canónica de iniciar múltiples actividades anidadas y obtener un resultado onActivityResult
- Sustitución de las inyecciones de Proveedor por Mockito durante la prueba con Dagger