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).
fonte
2012-06-26 14:25:43
Non sarà questo li causare ad essere fuori sincrono (non indispensabile qui) , specialmente quelli che vengono avviati più tardi? – Matthew
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
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