Frammenti e animazioni Android


265

Come dovresti implementare il tipo di scorrimento che ad esempio utilizza il client Honeycomb Gmail?

Può TransactionManagergestirlo automaticamente aggiungendo e rimuovendo i frammenti, è un po 'difficile testarlo a causa dell'emulatore che è una presentazione :)

Risposte:


388

Per animare la transizione tra i frammenti o per animare il processo di mostrare o nascondere un frammento, si utilizza Fragment Managerper creare un Fragment Transaction.

All'interno di ciascuna Transazione di frammenti è possibile specificare animazioni in entrata e in uscita che verranno utilizzate rispettivamente per mostrare e nascondere (o entrambe quando si usa la sostituzione).

Il codice seguente mostra come sostituire un frammento estraendo un frammento e facendo scorrere l'altro al suo posto.

FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);

DetailsFragment newFragment = DetailsFragment.newInstance();

ft.replace(R.id.details_fragment_container, newFragment, "detailFragment");

// Start the animated transition.
ft.commit();

Per ottenere la stessa cosa nascondendo o mostrando un frammento che chiameresti semplicemente ft.showo ft.hide, passando nel frammento che desideri mostrare o nascondere rispettivamente.

Per riferimento, le definizioni di animazione XML utilizzerebbero il objectAnimatortag. Un esempio di slide_in_left potrebbe assomigliare a questo:

<?xml version="1.0" encoding="utf-8"?>
<set>
  <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:propertyName="x" 
    android:valueType="floatType"
    android:valueFrom="-1280"
    android:valueTo="0" 
    android:duration="500"/>
</set>

57
Quando l'ho provato, mostra RuntimeException: nome animatore sconosciuto: tradurre .
Labeeb Panampullan,

3
Assicurati che le animazioni definite in slide_in_left e right siano costruite usando una serie di definizioni objectAnimator piuttosto che la vecchia definizione di animazione.
Reto Meier,

7
Questo ha aiutato molto. Ero sulla strada giusta, ma non sono arrivato fino in fondo. Per gli altri lettori, potresti anche avere android: interpolator come attributo, con il tuo preferito preferito specificato (come "@android: interpolator / linear"). L'impostazione predefinita è "@android: interpolator / accelerate_decelerate".
Dave MacLean,

6
Sto prendendo di mira l'API Level 7 con le API di compatibilità. C'è un modo per animare i frammenti?
Jarrod Smith,

5
@JarrodSmith puoi provare a utilizzare una libreria di compatibilità come NineOldAndroids per portare l'API Honeycomb su Eclair.
Mr. S

249

Se non devi usare la libreria di supporto, dai un'occhiata alla risposta di Roman .

Ma se si desidera utilizzare la libreria di supporto, è necessario utilizzare il vecchio framework di animazione come descritto di seguito.

Dopo aver consultato le risposte di Reto e blindstuff, ho ottenuto il seguente codice funzionante.

I frammenti appaiono scivolando da destra e scivolando verso sinistra quando si preme indietro.

FragmentManager fragmentManager = getSupportFragmentManager();

FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.setCustomAnimations(R.anim.enter, R.anim.exit, R.anim.pop_enter, R.anim.pop_exit);

CustomFragment newCustomFragment = CustomFragment.newInstance();
transaction.replace(R.id.fragment_container, newCustomFragment );
transaction.addToBackStack(null);
transaction.commit();

L'ordine è importante Questo significa che devi chiamare setCustomAnimations()prima replace()o l'animazione non avrà effetto!

Successivamente questi file devono essere inseriti nella cartella res / anim .

enter.xml :

<?xml version="1.0" encoding="utf-8"?>
<set>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
               android:fromXDelta="100%"
               android:toXDelta="0"
               android:interpolator="@android:anim/decelerate_interpolator"
               android:duration="@android:integer/config_mediumAnimTime"/>
</set>

exit.xml :

<set>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
               android:fromXDelta="0"
               android:toXDelta="-100%"
               android:interpolator="@android:anim/accelerate_interpolator"
               android:duration="@android:integer/config_mediumAnimTime"/>
</set>

pop_enter.xml :

<set>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
               android:fromXDelta="-100%"
               android:toXDelta="0"
               android:interpolator="@android:anim/decelerate_interpolator"
               android:duration="@android:integer/config_mediumAnimTime"/>
</set>

pop_exit.xml :

<?xml version="1.0" encoding="utf-8"?>
<set>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
               android:fromXDelta="0"
               android:toXDelta="100%"
               android:interpolator="@android:anim/accelerate_interpolator"
               android:duration="@android:integer/config_mediumAnimTime"/>
</set>

La durata delle animazioni può essere modificata in uno dei valori predefiniti come @android:integer/config_shortAnimTimeo in qualsiasi altro numero.

Si noti che se tra le sostituzioni di frammenti si verifica una modifica della configurazione (ad esempio rotazione) l'azione posteriore non viene animata. Questo è un bug documentato che esiste ancora nel rev 20 della libreria di supporto.


47
Questo mi ha appena salvato. Nota, prestare attenzione all'ordine è importante , che, naturalmente, ho perso la prima volta. Questo significa che devi chiamare setCustomAnimations () prima di sostituire ().
Stephen Kidson,

3
Ho cercato di implementare i miei frammenti. Ho scritto tutto come hai detto, ma logcat dice: sconosciuto nome animatore tradurre Come posso risolvere questo problema? A proposito, sto chiamando il mio frammento su Navigation Drawer (Menu scorrevole)
Zafer Celaloglu,

Funziona alla grande ma si scopre che la creazione di questo con gli strumenti di creazione 21.1 genera un errore che dice "Nome file non valido: deve contenere solo lettere minuscole e cifre ([a-z0-9_.])". Suggerisco di modificare i nomi dei file nella risposta a pop_enter.xml e pop_exit.xml.
Smichak,

Ottima soluzione e funziona benissimo quando premo il pulsante Indietro. Ho solo una domanda: se voglio creare un backButton personalizzato, quale codice dovrei chiamare per replicare il comportamento dal pulsante back?
Thomas Teilmann,

1
Thomas, se vuoi tornare indietro, dovresti implementare questo modulo: .setCustomAnimations (R.anim.pop_enter, R.anim.pop_exit, R.anim.enter, R.anim.exit)
Alex Zaraos

26

Consiglio vivamente di usare questo invece di creare il file di animazione perché è una soluzione molto migliore. Android Studio fornisce già impostazioni predefinite che animation è possibile utilizzare senza creare alcun nuovo file XML. I nomi delle animazioni sono android.R.anim.slide_in_left e android.R.anim.slide_out_right e puoi usarli come segue:

fragmentTransaction.setCustomAnimations (android.R.anim.slide_in_left, android.R.anim.slide_out_right);

FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();              
fragmentTransaction.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
fragmentManager.addOnBackStackChangedListener(this);
fragmentTransaction.replace(R.id.frame, firstFragment, "h");
fragmentTransaction.addToBackStack("h");
fragmentTransaction.commit();

Produzione:

inserisci qui la descrizione dell'immagine


1
android.R ... "Android Studio fornisce un'animazione predefinita", che non è per Android Studio, ma può funzionare anche in eclissi, Android.R è specifico per Android. E dal modo in cui non hai condiviso le informazioni su cosa hanno le API. roba su android.R sono diversi su diverse API.
Steve Moretz,

@stevemoretz thaxs bro Ho concordato il tuo punto .. Correggerò e aggiornerò la mia risposta ...
Gowthaman M

5

La mia libreria di supporto modificata supporta l'utilizzo di Visualizza animazioni (ad es. <translate>, <rotate>) E Animatori di oggetti (ad es. <objectAnimator>) Per le Transizioni di frammenti. È implementato con NineOldAndroids . Fare riferimento alla mia documentazione su Github per i dettagli.


2

Per quanto mi riguarda, ho bisogno della direzione di visualizzazione:

in -> scorri da destra

fuori -> scorri verso sinistra

Qui funziona per me il codice:

slide_in_right.xml

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate android:fromXDelta="50%p" android:toXDelta="0"
            android:duration="@android:integer/config_mediumAnimTime"/>
    <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
            android:duration="@android:integer/config_mediumAnimTime" />
</set>

slide_out_left.xml

 <set xmlns:android="http://schemas.android.com/apk/res/android">
        <translate android:fromXDelta="0" android:toXDelta="-50%p"
                android:duration="@android:integer/config_mediumAnimTime"/>
        <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
                android:duration="@android:integer/config_mediumAnimTime" />
    </set>

codice transazione:

inline fun FragmentActivity.setContentFragment(
        containerViewId: Int,
        backStack: Boolean = false,
        isAnimate: Boolean = false,
        f: () -> Fragment

): Fragment? {
    val manager = supportFragmentManager
    return f().apply {
        manager.beginTransaction().let {
            if (isAnimate)
                it.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left)

            if (backStack) {
                it.replace(containerViewId, this, "Fr").addToBackStack("Fr").commit()
            } else {
                it.replace(containerViewId, this, "Fr").commit()
            }
        }
    }
}

Android sembra sfarfallare le transizioni con quelle animazioni (specialmente quelle tradotte)
Gabriel De Oliveira Rohden

@GabrielDeOliveiraRohden come per me non in tutti i sensi
Serg Burlaka

1

Lo risolvo nel modo seguente

Animation anim = AnimationUtils.loadAnimation(this, R.anim.slide);
fg.startAnimation(anim);
this.fg.setVisibility(View.VISIBLE); //fg is a View object indicate fragment
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.