Pobierz bieżący obiekt fragmentu

175

W moim main.xmlmam

  <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>

I ustawiam obiekt fragmentu w ten sposób

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

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

Ustawia różne typy obiektów Fragment ( FragmentType2,FragmentType3,...) w różnym czasie. Teraz w pewnym momencie muszę zidentyfikować, który obiekt obecnie się tam znajduje.

W skrócie muszę zrobić coś takiego:

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

Wypróbowałem następujące

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

i

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

Ale oba obiekty (titleFragmentById i titleFragmentByTag) są.null
Czy coś mi umknęło?
Używam Compatibility Package, r3i rozwijam się dla API level 7.

findFragmentById()i findFragmentByTag()będzie działać, jeśli ustawiliśmy fragment za pomocą fragmentTransaction.replacelub fragmentTransaction.add, ale będzie, return nulljeśli ustawiliśmy obiekt na xml (tak jak to, co zrobiłem w moim main.xml). Myślę, że brakuje mi czegoś w moich plikach XML.

Labeeb Panampullan
źródło
Powiązane - stackoverflow.com/a/21104084/80428
Jay Wick
Czy odpowiedź @CommonsWare Ci pomaga, ponieważ nadal otrzymuję wartość null?
IntoTheDeep

Odpowiedzi:

253

Teraz w pewnym momencie muszę zidentyfikować, który obiekt obecnie się tam znajduje

Zadzwoń findFragmentById()na FragmentManageri ustalić, który fragment jest w R.id.frameTitlepojemniku.

CommonsWare
źródło
1
Dzięki za twoją odpowiedź. Będzie działać, jeśli ustawiliśmy fragment za pomocą fragmentTransaction.replace lub, fragmentTransaction.addale nie otrzymamy, jeśli ustawiliśmy go na xml. Zobacz moją edycję 2
Labeeb Panampullan
9
@Labeeb P: Nie możesz modyfikować fragmentów zadeklarowanych w zasobach układu.
CommonsWare,
Stworzenie klasy do przechowywania aktualnie widocznej zakładki / fragmentu również zadziała, właśnie tego próbowałem. Mam nadzieję, że nie ma błędów.
Skynet
@CommonsWare findFragmentByTagzwraca wartość null w przypadku ActionBartabulatorów. W moim, Activityktóry jest rozszerzany, ActionBarActivitynajpierw dodaję karty, ActionBara potem je znajduję!
Muhammad Babar
1
@MuhammadBabar: Można spróbować executePendingTransactions()na FragmentManagerpo wywołaniu commit()na transakcji, chociaż nie próbowałem tego. Możesz też użyć setContentView()pliku układu z <fragment>tagiem. Każde z nich dzieje się synchronicznie, więc fragment będzie istniał w samym onCreate()wywołaniu, w którym użyłeś executePendingTransaction()lub setContentView(). W przeciwnym razie zwykły FragmentTransactionjest przetwarzany asynchronicznie i nie zacznie się nawet przed upływem czasu onCreate().
CommonsWare
110

Spróbuj tego,

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

to da ci aktualny fragment, potem możesz porównać go z klasą fragmentu i zrobić swoje.

    if (currentFragment instanceof NameOfYourFragmentClass) {
     Log.v(TAG, "find the current fragment");
  }
Młotek
źródło
Gdzie umieścić tę linię?
Anand Savjani,
9
Czasami musisz użyć getSupportFragmentManager()zamiast tego i otrzymasz zero bez supportczęści
Muz
Usuń cytaty z obszaru „NAZWA TWOJEJ KLASY FRAGMENTU”.
Alan Nelson,
37

Myślę, że możesz użyć zdarzenia onAttachFragment, aby złapać, który fragment jest aktywny.

@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();

}
Hede Hodo
źródło
3
mogę sprawdzić, do którego fragmentu jestem dołączony. Uważam, że kiedy zmieniam orientację, muszę wyświetlić ten sam widok, a nie inny widok, więc jak to zrobić.
Androi Developer
7
To nie działa, ponieważ nie aktualizuje aktywnego fragmentu po powrocie.
Justin
1
@Justin, więc musimy tylko użyć onDetach również z listą
słabych referencji
12

Myślę, że powinieneś zrobić:

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

Powodem jest to, że ustawiłeś znacznik „fragmentTag” na ostatni dodany fragment (podczas wywoływania zamiany).

Niqo
źródło
Dzięki, poprawiłem to. Pisząc to pytanie, popełniono błąd. Będzie działać, jeśli ustawiliśmy fragment za pomocą fragmentTransaction.replace lub, fragmentTransaction.addale nie otrzymamy, jeśli ustawiliśmy go na xml. Zobacz moją edycję 2
Labeeb Panampullan
Dziękuję bardzo! Rozwiązałem mój problem!
Jonas Gröger
2
czy to rozwiązanie nie oznacza, że ​​musisz umieścić ten sam tag dla wielu fragmentów? w przeciwnym razie skąd wiesz, że fragmentTagjest tagiem dla bieżącego fragmentu?
Thupten
12

Możesz pobrać listę fragmentów i zajrzeć do ostatniego.

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

Ale czasami (po przejściu wstecz) rozmiar listy pozostaje taki sam, ale niektóre z ostatnich elementów są puste. Więc na liście iterowałem do ostatniego niezerowego fragmentu i użyłem go.

    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;
                }
            }
        }
    }
eluleci
źródło
3
Nie używaj tej getFragments()metody. Jest oznaczony @hidei nie miał być dołączony do jar biblioteki wsparcia. Nie należy go traktować jako części eksportowanego interfejsu API.
James Wald,
Heh, więc powinni byli stworzyć metodę, która pozwoli ci robić dokładnie to, co getFragments()robi, ponieważ potrzebujesz jej dość często. Myślę, że jest teraz również publicznie dostępny.
EpicPandaForce
10

To najprostsze rozwiązanie i działa dla mnie.

1.) dodajesz swój fragment

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

}
Gau
źródło
9

Może być późno, ale mam nadzieję, że pomoże to komuś innemu, również @CommonsWare opublikował poprawną odpowiedź.

FragmentManager fm = getSupportFragmentManager();
Fragment fragment_byID = fm.findFragmentById(R.id.fragment_id);
//OR
Fragment fragment_byTag = fm.findFragmentByTag("fragment_tag");
Ahmad Ali Nasir
źródło
9
Nie pozwala to na uzyskanie aktywnego fragmentu, ponieważ niekoniecznie znasz identyfikator lub tag.
Justin
7

Może najprostszy sposób to:

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;
}

U mnie to zadziałało

madx
źródło
6

Możesz utworzyć pole w swojej rodzicielskiej klasie aktywności:

public class MainActivity extends AppCompatActivity {

    public Fragment fr;

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

}

A następnie wewnątrz każdej klasy fragmentów:

public class SomeFragment extends Fragment {

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

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

Twoje pole 'fr' to aktualny fragment Object

Działa również z popBackStack ()

buxik
źródło
4

Wiem, że minęło trochę czasu, ale zrobię to tutaj na wypadek, gdyby to komuś pomogło.

Zdecydowanie właściwą odpowiedzią jest (i wybrana) odpowiedź z CommonsWare. Miałem ten sam problem, co wysłany, następujący

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

ciągle zwracał zero. Mój błąd był naprawdę głupi, w moim pliku xml:

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

Błąd polegał na tym, że miałem android: tag ZAMIAST android: id .

Chayemor
źródło
2

Odpowiedź @ Hammer zadziałała dla mnie, używam do sterowania pływającym przyciskiem akcji

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);
            }
        }
});
Thiago Melo
źródło
2

Jeśli rozszerzasz z AbstractActivity, możesz użyć metody getFragments ():

for (Fragment f : getFragments()) {
    if (f instanceof YourClass) {
        // do stuff here
    }
}
Marco Aurélio Alves Puton
źródło
1

Jeśli definiujesz fragment w warstwie XML działania, Activityupewnij się, że dzwonisz setContentView()przed wywołaniem findFragmentById().

IvancityM
źródło
1

Jeśli używasz BackStack ... I TYLKO jeśli używasz tylnego stosu, spróbuj tego:

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;
}
James Barwick
źródło
0

W ten sposób otrzymasz aktualną nazwę klasy fragmentu ->

String fr_name = getSupportFragmentManager().findFragmentById(R.id.fragment_container).getClass().getSimpleName();
Biplob Das
źródło
0
  1. Sprawdź (który fragment w kontenerze aktywności) w metodzie onStart;

    @Override
    protected void onStart() {
    super.onStart();
    Fragment fragmentCurrent = getSupportFragmentManager.findFragmentById(R.id.constraintLayout___activity_main___container);
    }
  2. Niektórzy sprawdzają:

    if (fragmentCurrent instanceof MenuFragment) 
Владислав Шестернин
źródło