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.



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.


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

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

}

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


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

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

}

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");

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


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


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 .


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

2

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

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

1

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


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

0

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

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

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) 
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.