Ottieni l'oggetto frammento corrente


175

Nel mio main.xmlho

  <FrameLayout
        android:id="@+id/frameTitle"
        android:padding="5dp"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent"
        android:background="@drawable/title_bg">
            <fragment
              android:name="com.fragment.TitleFragment"
              android:id="@+id/fragmentTag"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content" />

  </FrameLayout>

E sto impostando un frammento come questo

FragmentManager fragmentManager = activity.getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Fragment newFragment = new FragmentType1();
fragmentTransaction.replace(R.id.frameTitle, casinodetailFragment, "fragmentTag");

// fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();

Sta impostando diversi tipi di oggetti Fragment ( FragmentType2,FragmentType3,...) in momenti diversi. Ora ad un certo punto ho bisogno di identificare quale oggetto è attualmente lì.

In breve, devo fare qualcosa del genere:

Fragment currentFragment = //what is the way to get current fragment object in FrameLayout R.id.frameTitle

Ho provato quanto segue

TitleFragment titleFragmentById = (TitleFragment) fragmentManager.findFragmentById(R.id.frameTitle);

e

    TitleFragment titleFragmentByTag = (TitleFragment) fragmentManager.findFragmentByTag("fragmentTag");

Ma entrambi gli oggetti (titleFragmentById e titleFragmentByTag)null
mi sono perso qualcosa?
Sto usando Compatibility Package, r3e sviluppando per API level 7.

findFragmentById()e findFragmentByTag()funzionerà se abbiamo impostato il frammento usando fragmentTransaction.replaceo fragmentTransaction.add, ma funzionerà return nullse abbiamo impostato l'oggetto su xml (come quello che ho fatto nel mio main.xml). Penso che mi manchi qualcosa nei miei file XML.



La risposta di @CommonsWare ti aiuta, perché continuo a essere null?
IntoTheDeep,

Risposte:


253

Ora ad un certo punto ho bisogno di identificare quale oggetto è attualmente lì

Chiamare findFragmentById()su FragmentManagere determinare quale frammento è nel vostro R.id.frameTitlecontenitore.


1
Grazie per la risposta. Funzionerà se abbiamo impostato il frammento usando fragmentTransaction.replace o fragmentTransaction.addma non lo otterremo se lo abbiamo impostato su xml. Vedi la mia modifica 2
Labeeb Panampullan,

9
@Labeeb P: non è possibile modificare i frammenti dichiarati nelle risorse di layout.
Commons War

Anche la creazione di una classe per contenere la scheda / il frammento attualmente visibile funzionerà, l'ho appena provato. Spero non ci siano fallimenti.
Skynet il

@CommonsWare findFragmentByTagrestituisce null in caso di ActionBarschede. Nel mio Activityche si sta estendendo ActionBarActivitysto prima aggiungendo le schede ActionBare poi trovandolo!
Muhammad Babar

1
@MuhammadBabar: Si può provare executePendingTransactions()su FragmentManagerdopo aver chiamato commit()l'operazione, anche se non ho provato questo. Oppure puoi usare setContentView()per usare un file di layout con un <fragment>tag. Ognuno di questi avviene in modo sincrono, e quindi il frammento esisterà all'interno della onCreate()chiamata stessa dove hai usato executePendingTransaction()o setContentView(). Altrimenti, un ordinario FragmentTransactionviene elaborato in modo asincrono e non sarà nemmeno iniziato entro la onCreate()fine del tempo .
CommonsWare,

110

Prova questo,

Fragment currentFragment = getActivity().getFragmentManager().findFragmentById(R.id.fragment_container);

questo ti darà il frammento attuale, quindi puoi confrontarlo con la classe del frammento e fare le tue cose.

    if (currentFragment instanceof NameOfYourFragmentClass) {
     Log.v(TAG, "find the current fragment");
  }

Dove mettere questa linea?
Anand Savjani,

9
A volte devi usare getSupportFragmentManager()invece, e diventerà nullo senza la supportparte
Muz

Rimuovi le virgolette da "NOME DELLA TUA FRAMMENT CLASS".
Alan Nelson,

37

Penso che puoi usare l' evento onAttachFragment può essere utile per individuare quale frammento è attivo.

@Override
public void onAttachFragment(Fragment fragment) {
    // TODO Auto-generated method stub
    super.onAttachFragment(fragment);

    Toast.makeText(getApplicationContext(), String.valueOf(fragment.getId()), Toast.LENGTH_SHORT).show();

}

3
posso ottenere quale frammento sono attaccato. Il mio obiettivo è quando cambio l'orientamento, quindi devo visualizzare la stessa vista, non un'altra vista, quindi come fare.
Androi Developer

7
Questo non funziona perché non aggiorna il frammento attivo quando torni indietro.
Giustino, il

1
@Justin quindi dobbiamo solo usare onDetach anche con un elenco di riferimenti
deboli

12

Penso che dovresti fare:

Fragment currentFragment = fragmentManager.findFragmentByTag("fragmentTag");

Il motivo è perché hai impostato il tag "fragmentTag" sull'ultimo frammento che hai aggiunto (quando hai chiamato sostituisci).


Grazie l'ho corretto. È un errore di battitura durante la scrittura di questa domanda. Funzionerà se abbiamo impostato il frammento usando fragmentTransaction.replace o fragmentTransaction.addma non lo otterremo se lo abbiamo impostato su xml. Vedi la mia modifica 2
Labeeb Panampullan,

Grazie mille! Risolto il mio problema!
Jonas Gröger,

2
questa soluzione non significa che devi mettere lo stesso tag per più frammenti? altrimenti come sapresti che fragmentTagè il tag per il frammento attuale?
Giovedì

12

È possibile ottenere l'elenco dei frammenti e guardare l'ultimo.

    FragmentManager fm = getSupportFragmentManager();
    List<Fragment> fragments = fm.getFragments();
    Fragment lastFragment = fragments.get(fragments.size() - 1);

Ma a volte (quando torni indietro) le dimensioni dell'elenco rimangono uguali ma alcuni degli ultimi elementi sono nulli. Quindi nella lista ho ripetuto l'ultimo frammento non nullo e l'ho usato.

    FragmentManager fm = getSupportFragmentManager();
    if (fm != null) {
        List<Fragment> fragments = fm.getFragments();
        if (fragments != null) {
            for(int i = fragments.size() - 1; i >= 0; i--){
                Fragment fragment = fragments.get(i);
                if(fragment != null) {
                    // found the current fragment

                    // if you want to check for specific fragment class
                    if(fragment instanceof YourFragmentClass) {
                        // do something
                    }
                    break;
                }
            }
        }
    }

3
Non usare il getFragments()metodo È contrassegnato da @hidee non doveva essere incluso nel vaso della libreria di supporto. Non dovrebbe essere considerato come parte dell'API esportata.
James Wald,

Eh, allora avrebbero dovuto creare un metodo che ti consente di fare esattamente ciò che getFragments()fa, perché ne hai bisogno abbastanza spesso. Penso che ora sia effettivamente disponibile anche al pubblico.
EpicPandaForce,

10

Questa è la soluzione più semplice e funziona per me.

1.) aggiungi il tuo frammento

ft.replace(R.id.container_layout, fragment_name, "fragment_tag").commit();

2.)

FragmentManager fragmentManager = getSupportFragmentManager();

Fragment currentFragment = fragmentManager.findFragmentById(R.id.container_layout);

if(currentFragment.getTag().equals("fragment_tag"))

{

 //Do something

}

else

{

//Do something

}

9

Potrebbe essere tardi, ma spero che aiuti qualcun altro, anche @CommonsWare ha pubblicato la risposta corretta.

FragmentManager fm = getSupportFragmentManager();
Fragment fragment_byID = fm.findFragmentById(R.id.fragment_id);
//OR
Fragment fragment_byTag = fm.findFragmentByTag("fragment_tag");

9
Questo non ti consente di ottenere il frammento attivo, poiché non conosci necessariamente l'id o il tag.
Giustino, il

7

Forse il modo più semplice è:

public MyFragment getVisibleFragment(){
    FragmentManager fragmentManager = MainActivity.this.getSupportFragmentManager();
    List<Fragment> fragments = fragmentManager.getFragments();
    for(Fragment fragment : fragments){
        if(fragment != null && fragment.getUserVisibleHint())
            return (MyFragment)fragment;
    }
    return null;
}

Ha funzionato per me


6

Puoi creare un campo nella tua classe di attività principale:

public class MainActivity extends AppCompatActivity {

    public Fragment fr;

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

}

E poi all'interno di ogni classe di frammento:

public class SomeFragment extends Fragment {

@Override
    public View onCreateView(LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {

        ((MainActivity) getActivity()).fr = this;
}

Il tuo campo "fr" è l'oggetto frammento corrente

Funziona anche con popBackStack ()


4

So che è passato un po 'di tempo, ma lo farò qui nel caso in cui aiuti qualcuno.

La risposta giusta è di gran lunga (e quella selezionata) quella di CommonsWare. Stavo avendo lo stesso problema pubblicato, il seguente

MyFragmentClass fragmentList = 
            (MyFragmentClass) getSupportFragmentManager().findFragmentById(R.id.fragementID);

ha continuato a restituire null. Il mio errore è stato davvero sciocco, nel mio file xml:

<fragment
    android:tag="@+id/fragementID"
    android:name="com.sf.lidgit_android.content.MyFragmentClass"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
/>

L'errore era che avevo android: tag INSTEAD OF android: id .


2

La risposta di @Hammer ha funzionato per me, sto usando per controllare un pulsante di azione mobile

final FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(final View view) {
            android.app.Fragment currentFragment = getFragmentManager().findFragmentById(R.id.content_frame);
            Log.d("VIE",String.valueOf(currentFragment));
            if (currentFragment instanceof PerfilFragment) {
                PerfilEdit(view, fab);
            }
        }
});

2

Se si sta estendendo da AbstractActivity, è possibile utilizzare il metodo getFragments ():

for (Fragment f : getFragments()) {
    if (f instanceof YourClass) {
        // do stuff here
    }
}

1

Se stai definendo il frammento nel livello XML dell'attività, Activityassicurati di chiamare setContentView()prima di chiamare findFragmentById().


1

Se si utilizza BackStack ... e SOLO se si utilizza lo stack posteriore, provare questo:

rivate Fragment returnToPreviousFragment() {

    FragmentManager fm = getSupportFragmentManager();

    Fragment topFrag = null;

    int idx = fm.getBackStackEntryCount();
    if (idx > 1) {
        BackStackEntry entry = fm.getBackStackEntryAt(idx - 2);
        topFrag = fm.findFragmentByTag(entry.getName());
    }

    fm.popBackStack();

    return topFrag;
}

0

Questo ti darà l'attuale nome della classe del frammento ->

String fr_name = getSupportFragmentManager().findFragmentById(R.id.fragment_container).getClass().getSimpleName();

0
  1. Esegui un controllo (quale frammento nel contenitore delle attività) nel metodo onStart;

    @Override
    protected void onStart() {
    super.onStart();
    Fragment fragmentCurrent = getSupportFragmentManager.findFragmentById(R.id.constraintLayout___activity_main___container);
    }
  2. Alcuni controlli:

    if (fragmentCurrent instanceof MenuFragment) 
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.