2012-06-25 18 views
20

Al primo clic di un pulsante, voglio far scorrere uno View lungo l'asse x (di 200 pixel a destra diciamo). E alla seconda pressione del pulsante, voglio far scorrere lo View indietro lungo l'asse x nella sua posizione originale.Come animare la traduzione di una vista

Il metodo View.setTranslationX(float)salta la vista alle posizioni orizzontali di destinazione con chiamate myView.setTranslationX(200); e myView.setTranslationX(0); rispettivamente. Qualcuno sa come posso fare scorrere il View alle posizioni orizzontali di destinazione invece?

Nota 1: A TranslateAnimation non va bene dal momento che in realtà non si muove il View ma presenta solo l'illusione di essa in movimento.

Nota 2: Non mi rendevo conto al momento della posa della questione che i metodi setTranslationX(float) e setTranslationY(float) sono stati introdotti come di API Livello 11. Se ci si rivolge a nido d'ape (Livello API 11) verso l'alto, poi Gautam La risposta di K sarà sufficiente. Altrimenti, vedi la mia risposta per una soluzione suggerita.

risposta

5

Questo mi ha costretto per un paio di giorni (riuscendo a lavorare pre Ice Cream Sandwich) ma penso Finalmente sono arrivato!(grazie a Gautam K e Mike Israel per i lead) Quello che ho fatto alla fine è stato estendere il mio View (a FrameLayout) per avviare le animazioni destra/sinistra di traduzione come richiesto e per ascoltare la fine delle animazioni per trasferirsi il mio FrameLayout destra/sinistra a seconda dei casi, come segue:

public class SlidingFrameLayout extends FrameLayout 
{ 
    private final int durationMilliseconds = 1000; 
    private final int displacementPixels = 200; 

    private boolean isInOriginalPosition = true; 
    private boolean isSliding = false; 

    public SlidingFrameLayout(Context context) 
    { 
    super(context); 
    } 

    public SlidingFrameLayout(Context context, AttributeSet attrs) 
    { 
    super(context, attrs); 
    } 

    public SlidingFrameLayout(Context context, AttributeSet attrs, int defStyle) 
    { 
    super(context, attrs, defStyle); 
    } 

    @Override 
    protected void onAnimationEnd() 
    { 
    super.onAnimationEnd(); 

    if (isInOriginalPosition) 
     offsetLeftAndRight(displacementPixels); 
    else 
     offsetLeftAndRight(-displacementPixels); 

    isSliding = false; 
    isInOriginalPosition = !isInOriginalPosition; 
    } 

    @Override 
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) 
    { 
    super.onLayout(changed, left, top, right, bottom); 

    // need this since otherwise this View jumps back to its original position 
    // ignoring its displacement 
    // when (re-)doing layout, e.g. when a fragment transaction is committed 
    if (changed && !isInOriginalPosition) 
     offsetLeftAndRight(displacementPixels); 
    } 

    public void toggleSlide() 
    { 
    // check whether frame layout is already sliding 
    if (isSliding) 
     return; // ignore request to slide 

    if (isInOriginalPosition) 
     startAnimation(new SlideRightAnimation()); 
    else 
     startAnimation(new SlideLeftAnimation()); 

    isSliding = true; 
    } 

    private class SlideRightAnimation extends TranslateAnimation 
    { 
    public SlideRightAnimation() 
    { 
     super(
      Animation.ABSOLUTE, 0, 
      Animation.ABSOLUTE, displacementPixels, 
      Animation.ABSOLUTE, 0, 
      Animation.ABSOLUTE, 0); 

     setDuration(durationMilliseconds); 
     setFillAfter(false); 
    } 
    } 

    private class SlideLeftAnimation extends TranslateAnimation 
    { 
    public SlideLeftAnimation() 
    { 
     super(
      Animation.ABSOLUTE, 0, 
      Animation.ABSOLUTE, -displacementPixels, 
      Animation.ABSOLUTE, 0, 
      Animation.ABSOLUTE, 0); 

     setDuration(durationMilliseconds); 
     setFillAfter(false); 
    } 
    } 
} 

E, infine, di far scorrere il SlidingFrameLayout destra/sinistra, tutto quello che devi fare è chiamare il metodo SlidingFrameLayout.toggleSlide(). Naturalmente puoi modificare questo SlidingFrameLayout per far scorrere un numero maggiore di pixel, scorrere più a lungo ecc, ma questo dovrebbe essere sufficiente per iniziare :)

25

Prova a guardare nella ObjectAnimator e la sua super-classe di valore Animator

si può fare qualcosa di simile ObjectAnimator anim = ObjectAnimator.ofFloat(this, "translationX", 0,200); e poi anim.start();

utilizzare un valore boolean e alternare con 200,0 nel animatore oggetto per scorrere indietro

PS: è possibile utilizzare setDuration metodo per impostare per quanto tempo l'animazione dovrebbe prendere per completare

Edit:

Prova a guardare il support library che fornisce la compatibilità all'indietro.

Modifica

Come @AdilHussain sottolineato c'è una libreria chiamata nineoldandroids che può essere utilizzato per lo stesso scopo in androidi più anziani.

+0

@AdilHussain: allora devi implementare la funzionalità con i thread te stesso su telefoni che non lo supportano. Basta controllare se il telefono lo supporta o scrivere qualche semplice ripiego. Questa è l'opzione migliore. – Gautam

+1

Ho trovato questa brillante libreria che fa il lavoro: [http://nineoldandroids.com] (http://nineoldandroids.com). Libreria disponibile per il download come 'jar' da qui: [https://github.com/JakeWharton/NineOldAndroids/downloads](https://github.com/JakeWharton/NineOldAndroids/downloads) –

+1

Sembra che abbia parlato troppo presto. Quando esegui una traduzione utilizzando la libreria [nineoldandroids] (https://github.com/JakeWharton/NineOldAndroids) su telefoni meno recenti (pre-Honeycomb), i pulsanti all'interno della visualizzazione tradotta sembrano essere stati spostati ma sono ancora selezionabili nelle loro vecchie posizioni (e non le loro nuove posizioni). Ho inviato un'email all'autore della biblioteca ma non ho ancora ricevuto una risposta. –

2

Avevo un problema simile, TranslateAnimation sposta effettivamente la vista se si chiama setFillAfter ora (android bug). Ho dovuto fare qualcosa di simile, così ho detto, hey lascia usare un listener di animazione e poi sposta semplicemente tutto nella posizione corretta. Sfortunatamente c'è anche un bug negli ascoltatori di animazione (stackoverflow solution). Così ho creato la mia classe di layout in base alla soluzione nel stackoverflow solution ed ero a posto :)

+0

Grazie per la risposta e i collegamenti. Va a dimostrare che l'uso di "TranslateAnimation" per questo è un po 'disordinato. Quando ho detto "TranslateAnimation" in realtà non sposta la vista (nonostante l'utilizzo di 'setFillAfter (true)'), intendevo dire che gli elementi cliccabili sono ancora nelle loro posizioni originali. Guarda questo video per un esempio di ciò che intendo: [http://www.youtube.com/watch?v=VY3kMFrA3wU](http://www.youtube.com/watch?v=VY3kMFrA3wU) –

+1

sì, sembra esattamente come il bug con fillAfter. Strano però che il primo pulsante funzioni, qual è la differenza tra i due pulsanti, nessuno? – MikeIsrael

+1

La soluzione che ho consigliato dovrebbe funzionare ancora per tutte le versioni. Ho creato una classe di layout personalizzata che sostituisce onAnimationEnd() e lì cambio il margine dell'oggetto come necessario per spostarlo nel punto corretto. – MikeIsrael

Problemi correlati