2011-10-26 4 views
39

Ok, donc j'ai vérifié http://android-developers.blogspot.com/2011/02/animation-in-honeycomb.htmlObjectAnimator animation LinearLayout largeur

Il dit que vous pouvez animer la propriété d'un objet dans un temps donné. Et j'ai essayé de déplacer des objets et ça a l'air bien. J'ai rencontré un problème quand je suis allé changer la largeur d'un LinearLayout. Je suis arrivé ceci:

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

Alors j'ai essayé étendre LinearLayout, avec "myWidth"

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

Pas de chance. Ensuite, j'ai essayé de changer LayoutParams.width, il s'avère que la largeur et la hauteur sont les seules propriétés publiques dans l'histoire java, et ObjectAnimator a besoin de getter et setter. Pas de chance. Je suis gêné de dire que j'ai essayé d'étendre LayoutParams aussi ... sans aucune chance ofc.

Quelqu'un a-t-il réussi à faire une telle chose? J'ai utilisé vieux android.view.animation et j'ai eu ce que je voulais, mais je suis curieux pour l'avenir.

+0

Malheureusement, j'ai un problème similaire. Au lieu d'animer la largeur, j'ai essayé d'animer le weightSum (qui a un getter/setter) pour obtenir le même effet. Peut-être que vous pouvez essayer quelque chose de similaire pour atteindre ce que vous voulez, mais je ne peux pas le faire fonctionner: http://stackoverflow.com/questions/8341745/animating-weightsum-property-using-objectanimator. Je vous tiendrai au courant si j'ai des résultats – Entreco

Répondre

19

Pour ce que ça vaut ça fonctionne. Après avoir modifié la largeur sur les paramètres de mise en page, vous devez réinitialiser l'objet params de la mise en page.

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

Pour que cela fonctionne avec nineOldAndroids, changez la signature de la méthode evaluate pour utiliser Integer au lieu de Object. 'public Integer evaluate (fraction flottante, Integer startValue, Integer endValue)' – loeschg

+0

N'utilisez pas d'évaluateurs pour effectuer des modifications de vue. Ajoutez un 'AnimatorUpdateListener' à la place. –

109

Dans les situations où il n'y a pas une simple propriété getter/setter vous devez utiliser ValueAnimator et effectuer manuellement l'animation.

Si l'on suppose:

  • v est la vue que vous animez
  • END_WIDTH est la largeur cible de la vue en pixels.
  • DURÉE est la longueur souhaitée de l'animation en millisecondes.

Votre code devrait ressembler à ceci:

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

l'inconvénient, à partir de 11 et plus ... – desgraci

+2

Vous pouvez utiliser http://nineoldandroids.com/ pour les anciennes versions. – lordmegamax

+0

Très bonne réponse, merci! – CyberDandy

6

Vous avez fait une erreur

params.weight = myWidth; 

Je pense qu'il est params.width pas params.weight

1

Je pense qu'un meilleur moyen d'accomplir ce wou ld sera d'utiliser les propriétés scaleX et scaleY de View qui sont définies tout au long dans la classe View, de sorte qu'il serait valide avec pratiquement n'importe quelle vue ou disposition.

Par exemple, considérons ce

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

Il fonctionne.

+4

Non, cela ne fonctionne pas. Cela met à l'échelle, c'est-à-dire étire la vue, ce qui est bien différent de simplement l'agrandir, en conservant intactes les proportions du contenu de la vue. –

5

J'ai créé une petite bibliothèque ViewPropertyObjectAnimator qui peut le faire d'une manière très simple (et utilise une approche similaire à celle proposée par Tomer Weller).

Vous pouvez réaliser cette animation avec (en supposant que le mLinearLayout est le film d'animation View et mEndWidth est la valeur finale de la largeur View's):

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

Belle bibliothèque, @Bartosz! –

+0

Merci @StephenKaiser :)! C'est assez simple mais très utile. –

Questions connexes