2011-10-26 32 views
39

Ok, por lo que el check out http://android-developers.blogspot.com/2011/02/animation-in-honeycomb.htmlObjectAnimator animar LinearLayout anchura

Dice que puede animar la propiedad de un objeto en un momento dado. Intenté mover objetos y parece estar bien. Encontré un problema cuando cambié el ancho de LinearLayout. Tengo esto:

10-26 14:51:27.190: E/PropertyValuesHolder(12681): Couldn't find setter/getter for  property width with value type float 

Luego probé extendiéndose LinearLayout, con "myWidth"

public void setMyWidth(int myWidth) { 
    LinearLayout.LayoutParams params = (LayoutParams) getLayoutParams(); 
    params.weight = myWidth; 
    setLayoutParams(params); 
    requestLayout(); 
    this.myWidth = myWidth; 
} 

No hubo suerte. Luego intenté cambiar LayoutParams.width, resulta que el ancho y la altura son las únicas propiedades públicas en el historial de Java, y ObjectAnimator necesita getter y setter. Sin suerte. Estoy avergonzado de decir que traté de extender LayoutParams también ... sin suerte.

¿Alguien ha tenido éxito en hacer tal cosa? Utilicé el viejo android.view.animation y obtuve lo que quería, pero tengo curiosidad por el futuro.

+0

Por desgracia, tengo un problema similar. En lugar de animar el ancho, traté de animar el weightSum (que tiene un getter/setter) para lograr el mismo efecto. Tal vez puedas probar algo similar para lograr lo que quieres, pero no puedo hacer que funcione: http://stackoverflow.com/questions/8341745/animating-weightsum-property-using-objectanimator. Los mantendré informados si tengo algunos resultados – Entreco

Respuesta

19

Por lo que vale, esto funciona. Después de cambiar el ancho en los parámetros de diseño, debe restablecer el objeto params de diseño.

private class WidthEvaluator extends IntEvaluator { 

    private View v; 
    public WidthEvaluator(View v) { 
     this.v = v; 
    } 

    @Override 
    public Object evaluate(float fraction, Object startValue, Object endValue) { 
     int num = (Integer)super.evaluate(fraction, startValue, endValue); 
     ViewGroup.LayoutParams params = v.getLayoutParams(); 
     params.width = num; 
     v.setLayoutParams(params); 
     return num; 
    } 
} 

// your client code 
ValueAnimator.ofObject(new WidthEvaluator(box), box.getWidth(), v.getWidth()).start(); 
+3

Para que esto funcione con nineOldAndroids, cambie la firma del método de evaluación para usar Entero en lugar de Objeto. 'público Integer evalúa (fracción flotante, Integer startValue, Integer endValue)' – loeschg

+0

No utilice evaluadores para realizar cambios en la vista. Agrega un 'AnimatorUpdateListener' en su lugar. –

109

En situaciones en las que no es una propiedad sencilla captador/definidor se debe utilizar ValueAnimator y realizar la animación de forma manual.

Suponiendo:

  • v es la vista desea animar
  • END_WIDTH es el ancho blanco de la vista en píxeles.
  • DURACIÓN es la duración deseada de la animación en milisegundos.

El código debería ser algo como esto:

ValueAnimator anim = ValueAnimator.ofInt(v.getMeasuredWidth(), END_WIDTH); 
    anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 
     @Override 
     public void onAnimationUpdate(ValueAnimator valueAnimator) { 
      int val = (Integer) valueAnimator.getAnimatedValue(); 
      ViewGroup.LayoutParams layoutParams = v.getLayoutParams(); 
      layoutParams.width = val; 
      v.setLayoutParams(layoutParams); 
     } 
    }); 
    anim.setDuration(DURATION); 
    anim.start(); 
+0

la desventaja, desde 11 en adelante ... – desgraci

+2

Puede usar http://nineoldandroids.com/ para versiones anteriores. – lordmegamax

+0

¡Muy buena respuesta, gracias! – CyberDandy

6

Usted ha cometido un error

params.weight = myWidth; 

Creo que es params.width no params.weight

1

Creo que una mejor manera de lograr esto Debería usar las propiedades scaleX y scaleY de View, que están definidas completamente en la clase View, por lo que serían válidas prácticamente con cualquier vista o diseño.

Por ejemplo, considere esto

ObjectAnimator objectAnimator=ObjectAnimator.ofFloat(MyLinearLayout,"ScaleX",0,1); 
objectAnimator.setDuration(300); 
objectAnimator.start(); 

Funciona.

+4

No, no funciona. Esta escala, es decir, se estira, la vista, que es muy diferente de simplemente agrandarla, manteniendo intactas las proporciones del contenido de la vista. –

5

He creado una pequeña biblioteca ViewPropertyObjectAnimator que puede hacer eso de una manera muy simple (y utiliza un enfoque similar al propuesto por Tomer Weller).

Se podría lograr esta animación con (suponiendo que el mLinearLayout es el View animada y mEndWidth es el valor final de la anchura View's):

ViewPropertyObjectAnimator.animate(mLinearLayout).width(mEndWidth).start(); 
+0

¡Buena biblioteca, @Bartosz! –

+0

Gracias @StephenKaiser :)! Es bastante simple pero muy útil. –