2012-02-09 11 views
17

C'è un modo per animare più viste contemporaneamente?Singola animazione: più viste

Quello che voglio fare è di tradurre le animazioni:

Ho 5 TextViews e 4 strisce colorate (RelativeLayouts pianura con uno sfondo). All'inizio delle animazioni, i punti sono impilati con TextViews in una riga orizzontale. Alla fine voglio che tutte le TextViews impilati tra le strisce:

enter image description here

Questo è molto semplice disegno, ma dimostra quello che voglio fare. C'è un modo per farlo con le animazioni, o devo usare le animazioni su tela.

risposta

4

Creare gli oggetti di animazione, quindi utilizzare collettivamente startAnimation su tutte le viste contemporaneamente. Quindi sarebbe qualcosa di simile:

TranslateAnimation anim1; 
TranslateAnimation anim2; 
TranslateAnimation anim3; 

// Setup the animation objects 

public void startAnimations() 
{ 
    //... collect view objects 
    view1.startAnimation(anim1); 
    view2.startAnimation(anim2); 
    view3.startAnimation(anim3); 
} 

Basta notare che i più animazioni che si hanno in corso in una sola volta, più lento sarà.

+1

Non sarà questo li causare ad essere fuori sincrono (non indispensabile qui) , specialmente quelli che vengono avviati più tardi? – Matthew

+0

Non proprio. In pratica, ciò che accade è quando si usa 'startAnimation' su una vista, inizia a invalidare se stesso fino a quando non viene raggiunta la posizione desiderata. Quando lo chiamate su tutte le viste in una volta, chiameranno 'invalidate()' su se stesse, quindi nel passaggio successivo del disegno ogni vista verrà disegnata nel loro frame successivo. Poiché stai chiamando tutto questo sul thread dell'interfaccia utente, nessuna delle animazioni verrà avviata fino a quando non sarai tornato da quel metodo. NOTA: l'utilizzo della struttura di animazione pre-Honeycomb sposta semplicemente la parte visiva della vista.L'utente non sarà in grado di fare clic su di esso. – DeeV

+0

Applico le animazioni con anim1.setFillAfter (true); e quindi per spostare effettivamente la vista usando i parametri di layout? (Dovrei solo provarlo, ma è tardi :) – Matthew

3

Sono riuscito a condividere una singola istanza di Animazione tra più viste. Almeno con un AlphaAnimation. Ho avuto un controllo ListView e un'animazione da applicare a un particolare figlio di tutte le visualizzazioni di elementi dell'elenco. Nel mio caso avrebbe dovuto essere possibile per le viste 'unirsi' e 'lasciare' l'animazione condivisa in qualsiasi momento e non dovrebbe influenzare in alcun modo le altre viste animate o interferire con l'animazione già in esecuzione. Per raggiungere questo obiettivo ho dovuto fare una copia regolata di AlphaAnimation di Android. Il mio caso d'uso è piuttosto speciale, ma lascia che sia qui solo nel caso in cui qualcuno abbia a che fare con un obiettivo simile a ListView.

/** 
* This class is a copy of android's stock AlphaAnimation with two adjustments: 
* - fromAlpha, toAlpha and duration are settable at any time. 
* - reset() method can be blocked. Reason: view.setAnimation() calls animation's reset() method 
* which is not intended in our use case. 
* For every new list item view we call setAnimation once for it's life time 
* and animation should not be reset because it is shared by all list item views and may be in progress. 
*/ 
public class MutableAlphaAnimation extends Animation { 
    private float mFromAlpha; 
    private float mToAlpha; 
    private boolean resetBlocked; 

    public MutableAlphaAnimation() { 
    } 

    public void start(float fromAlpha, float toAlpha, long duration) { 
     mFromAlpha = fromAlpha; 
     mToAlpha = toAlpha; 
     setDuration(duration); 
     setStartTime(START_ON_FIRST_FRAME); 
    } 

    public void setResetBlocked(boolean resetBlocked) { 
     this.resetBlocked = resetBlocked; 
    } 

    @Override 
    public void reset() { 
     if (! resetBlocked) super.reset(); 
    } 

    @Override 
    protected void applyTransformation(float interpolatedTime, Transformation t) { 
     final float alpha = mFromAlpha; 
     t.setAlpha(alpha + ((mToAlpha - alpha) * interpolatedTime)); 
    } 

    @Override 
    public boolean willChangeTransformationMatrix() { 
     return false; 
    } 

    @Override 
    public boolean willChangeBounds() { 
     return false; 
    } 
} 

Per impostare questa animazione a vista:

  animation.setResetBlocked(true); 
      view.setAnimation(animation); 
      animation.setResetBlocked(false); 

e di avviare un'animazione (precedentemente fissato dal setAnimation) due cose devono essere fatte:

 animation.start(0.0f, 1.0f, FADE_IN_DURATION); 

E dopo che si deve chiamare manualmente invalidate() su ogni vista che è influenzata dall'animazione.

Il solito startAnimation() invalida() per te, ma setAnimation no. (leggi il commento sul metodo View.setAnimation() nei sorgenti di Android).

49

È possibile utilizzare l'ObjectAnimator per animare la visualizzazione multipla come segue:

ArrayList<ObjectAnimator> arrayListObjectAnimators = new ArrayList<ObjectAnimator>(); //ArrayList of ObjectAnimators 

ObjectAnimator animY = ObjectAnimator.ofFloat(view, "y", 100f); 
arrayListObjectAnimators.add(animY); 

ObjectAnimator animX = ObjectAnimator.ofFloat(view, "x", 0f); 
arrayListObjectAnimators.add(animX); 
... 
ObjectAnimator[] objectAnimators = arrayListObjectAnimators.toArray(new ObjectAnimator[arrayListObjectAnimators.size()]); 
AnimatorSet animSetXY = new AnimatorSet(); 
animSetXY.playTogether(objectAnimators); 
animSetXY.setDuration(1000);//1sec 
animSetXY.start(); 
+2

L'unico svantaggio è che è nuovo dalla versione 11 (a nido d'ape) – Matthew

+3

Usa nineoldandroids per riportare l'API indietro alla 1.0 (http://nineoldandroids.com/) – Tushar

+0

+1 per mostrare come avviarli tutti insieme –

0

È possibile utilizzare AnimationSet

AnimatorSet decSet2 = new AnimatorSet(); 
     decSet2.playTogether(
       ObjectAnimator.ofFloat(view, "x",dX), 
       ObjectAnimator.ofFloat(view, "y",dY), 
       ObjectAnimator.ofFloat(mTextCancel, "x",dX), 
       ObjectAnimator.ofFloat(mTextCancel, "y", dY), 
       ObjectAnimator.ofArgb(mBtnOne, "visibility", View.VISIBLE, View.GONE), 
       ); 
     decSet2.setDuration(0); 
     decSet2.start();