tutoriales - Control preciso sobre las animaciones vectoriales dibujables de androides.
domestika svg (3)
ACTUALIZACIÓN: Solución encontrada! ¡Desplácese hacia abajo para mi respuesta aceptada!
Quiero animar varios elementos de una imagen y vincular la animación a la posición de ViewPagers (por lo que múltiples elementos se están transformando o volando según la página actual que se está arrastrando).
Entonces, ¿hay una manera de controlar con precisión el cuadro actual de la animación? Por ejemplo, supongamos que tengo este conjunto:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:interpolator="@android:anim/decelerate_interpolator"
android:duration="800"
android:propertyName="scaleY"
android:valueFrom="0"
android:valueTo="1" />
<objectAnimator
android:interpolator="@android:anim/decelerate_interpolator"
android:duration="800"
android:propertyName="scaleX"
android:valueFrom="0"
android:valueTo="1" />
<objectAnimator
android:interpolator="@android:anim/decelerate_interpolator"
android:duration="800"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="360" />
</set>
Archivo vectorial animado:
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/pre_signup_1" >
<target
android:name="plus_button"
android:animation="@anim/pre_signup_1_plus_container" />
<target
android:name="plus"
android:animation="@anim/pre_signup_1_plus_sign" />
</animated-vector>
Código Java para ejecutar la animación:
ImageView mImage1 = (ImageView) findViewById(R.id.image_1);
AnimatedVectorDrawableCompat animated = (AnimatedVectorDrawableCompat) mImage1.getDrawable();
animated.start();
¿Hay alguna forma de controlar la animación como setCurrentDuration(400)
que presumiblemente establecerá el estado actual de la animación a la mitad? Tal vez hay una manera de dividir ese vector dibujable en capas y animarlas mediante programación. ¡Gracias por adelantado!
¡Parece que es posible acceder a rutas y grupos dentro de VectorDrawableCompat
y animarlos / transformarlos como quieras!
Después de algunas investigaciones, terminé duplicando las siguientes clases del paquete android.support.graphics.drawable
: AndroidResources
, PathParser
, TypedArrayUtils
, VectorDrawableCommon
y VectorDrawableCompat
.
Luego, debemos hacer públicos los siguientes métodos y clases dentro de la clase VectorDrawableCompat
: getTargetByName
, VFullPath
y VFullPath
.
A continuación, en la clase VectorDrawableCompat
, elimine el bloque que verifica la versión de Android ( Build.VERSION.SDK_INT >= 23
). No sé por qué, pero si no lo haces, la animación no funcionará en la API de Android 23 en adelante (necesitas más investigación).
Puede que haya perdido un par de métodos privados, pero es solo cuestión de hacerlos públicos si tiene problemas.
Entonces, ahora tenemos acceso a las capas de nuestro VectorDrawable
! Este es un pequeño ejemplo de la escala de un grupo de vectores según la ViewPager
del ViewPager
:
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="276dp"
android:height="359dp"
android:viewportWidth="276"
android:viewportHeight="359">
<group
android:pivotX="205.5"
android:pivotY="214.5"
android:name="my_group">
<path
android:strokeColor="#4D394B"
android:strokeWidth="7"
android:strokeLineJoin="bevel"
android:fillColor="#1ED761"
android:pathData="M206.5,180 C186.9,180,171,195.9,171,215.5 S186.9,251,206.5,251
C226.1,251,242,235.1,242,215.5 S226.1,180,206.5,180 Z" />
<path
android:fillColor="#4D394B"
android:pathData="M210,211 L210,190 L202,190 L202,211 L181,211 L181,219 L202,219 L202,241 L210,241
L210,219 L232,219 L232,211 Z" />
</group>
</vector>
Y este es el código usado para animar el grupo:
ImageView myImageView;
VectorDrawableCompat.VGroup myVectorGroup;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_welcome);
myImageView = (ImageView) findViewById(R.id.image_1);
VectorDrawableCompat vectorDrawable = VectorDrawableCompat.create(getResources(), R.drawable.my_vector_drawable, null);
vectorDrawable.setAllowCaching(false); // Important to allow image updates
myVectorGroup = (VectorDrawableCompat.VGroup) vectorDrawable.getTargetByName("my_group");
myImageView.setImageDrawable(vectorDrawable);
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if(myVectorGroup != null && position < 1) {
myVectorGroup.setScaleX(1f - positionOffset);
myVectorGroup.setScaleY(1f - positionOffset);
myImageView.invalidate();
}
}
});
}
Necesito más pruebas para determinar la compatibilidad, ¡pero funciona por ahora!
Creo que no puedes hacer esto con AnimatedVectorDrawable / AnimatedVectorDrawableCompat programáticamente.
Una solución es usar una Lista de niveles que se pueda dibujar y animar sus niveles : pero necesitará muchas imágenes para que los niveles simulen la transición sin problemas. Estoy usando solo tres niveles aquí para hacer demostraciones.
Primero, definirá la lista de niveles dibujables de esta manera: res / drawable / my_level_list.xml
<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/level0"
android:maxLevel="0"/>
<item android:drawable="@drawable/level1"
android:maxLevel="1"/>
<item android:drawable="@drawable/level2"
android:maxLevel="2"/>
</level-list>
Luego en el archivo de diseño:
<ImageView
android:id="@+id/img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/my_level_list" />
Luego en tu actividad:
int MIN_LEVEL=0;
int MAX_LEVEL=2;
ImageView img=(ImageView)findViewById(R.id.img);
Drawable myLevelSetDrawable= img.getDrawable();
ObjectAnimator anim=ObjectAnimator.ofInt(myLevelSetDrawable,"level",MIN_LEVEL,MAX_LEVEL);
anim.setInterpolator(new BounceInterpolator());
AnimatorSet set=new AnimatorSet();
set.play(anim);
set.setDuration(1000);
set.start();
Espero que ayude.
Por lo que dice la documentación para AnimatedVectorDrawables, no hay forma de rastrear el estado de la animación o de saltar a otro estado que no sea la animación de inicio y la animación.
Puede que tenga que usar una solución personalizada para lograr este efecto. Esta publicación en el blog explica una manera de utilizar el seguimiento de estado de los widgets de Android para lograr un efecto similar.