Отримайте поточний об’єкт фрагмента


175

В моєму main.xmlє

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

І я встановлюю такий предмет фрагмента

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

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

Він встановлює різні типи об'єктів Fragment ( FragmentType2,FragmentType3,...) в різний час. Зараз мені в якийсь момент потрібно визначити, який об’єкт зараз є.

Коротше кажучи, мені потрібно зробити щось подібне:

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

Я спробував наступне

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

і

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

Але обидва об'єкти (titleFragmentById та titleFragmentByTag)null
чи я щось пропустив?
Я використовую Compatibility Package, r3і розробляю для API level 7.

findFragmentById()і findFragmentByTag()буде працювати, якщо ми встановили фрагмент за допомогою fragmentTransaction.replaceабо fragmentTransaction.add, але буде, return nullякщо ми встановили об'єкт у xml (як, що я зробив у своєму main.xml). Я думаю, що мені щось не вистачає у файлах XML.



Чи допомагає вам відповідь @CommonsWare, тому що я все-таки став нульовим?
IntoTheDeep

Відповіді:


253

Зараз мені в якийсь момент потрібно визначити, який об’єкт зараз є

Виклик findFragmentById()на FragmentManagerі визначити , який фрагмент знаходиться в вашому R.id.frameTitleконтейнері.


1
Дякую за Вашу відповідь. Він буде працювати, якщо ми встановили фрагмент за допомогою fragmentTransaction.replace або fragmentTransaction.addне отримаємо, якщо ми встановили його у xml. Дивіться мою
редакцію

9
@Labeeb P: Ви не можете змінювати фрагменти, оголошені в ресурсах компонування.
CommonsWare

Створення класу для розміщення в даний час видимої вкладки / фрагмента також буде працювати, я спробував це. Сподіваюсь, що невдач немає.
Skynet

@CommonsПереводимо findFragmentByTagнульовий випадок у випадку ActionBarTabs. У моєму, Activityщо продовжує, ActionBarActivityя спочатку додаю вкладки, ActionBarа потім знаходжу його!
Мухаммед Бабар

1
@MuhammadBabar: Ви можете спробувати executePendingTransactions()на FragmentManagerпісля виклику commit()на операцію, хоча я не пробував. Або ви можете використовувати setContentView()файл макета з <fragment>тегом. Будь-який з них відбувається синхронно, і таким чином фрагмент буде існувати в самому onCreate()дзвінку, де ви використовували executePendingTransaction()або setContentView(). Інакше звичайний FragmentTransactionобробляється асинхронно, і він навіть не розпочнеться до кінця часу onCreate().
CommonsWare

110

Спробуйте це,

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

це дасть u поточний фрагмент, тоді ви можете порівняти його з класом фрагмента і виконати свої наповнення.

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

Куди поставити цю лінію?
Ананд Савжані

9
Іноді вам доведеться використовувати getSupportFragmentManager()замість цього, і ви отримаєте null без supportчастини
Muz

Вилучіть цитати з "НАЗВА ВАШОГО КЛАСУ ФРЕГМЕНТУ".
Алан Нельсон

37

Я думаю, що ви можете використовувати подію onAttachFragment, можливо, буде корисним, щоб визначити, який фрагмент активний.

@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
я можу отримати фрагмент, який я додаю. Моя думка - коли я змінюю орієнтацію, тоді мені потрібно відображати той самий вигляд, а не інший вигляд.
Androi Developer

7
Це не працює, оскільки він не оновлює активний фрагмент, коли ви повернетесь назад.
Джастін

1
@Justin, тому нам просто потрібно використовувати onDetach також зі списком
слабких референцій

12

Я думаю, вам слід зробити:

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

Причина полягає в тому, що ви встановлюєте тег "fragmentTag" на останній доданий вами фрагмент (коли ви викликали заміну).


Дякую, що я виправив це. Під час написання цього питання помилка друку. Він буде працювати, якщо ми встановили фрагмент за допомогою fragmentTransaction.replace або fragmentTransaction.addне отримаємо, якщо ми встановили його у xml. Дивіться мою
редакцію

Дуже дякую! Вирішили моє питання!
Йонас Грьогер

2
чи не означає це рішення, що вам потрібно поставити один і той же тег для кількох фрагментів? інакше як би ви знали, що fragmentTagце тег для поточного фрагмента?
Thupten

12

Ви можете отримати список фрагментів і подивитися до останнього.

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

Але іноді (коли ви переходите назад) розмір списку залишається однаковим, але деякі з останніх елементів є нульовими. Тож у списку я повторив останній ненульовий фрагмент і використав його.

    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
Не використовуйте getFragments()метод. Він позначений символом @hideі не повинен був включатись у банку підтримки бібліотеки. Це не повинно розглядатися як частина експортованого API.
Джеймс Уолд

Хе, тоді вони мали б створити метод, який дозволяє вам робити саме те, що getFragments()робить, тому що це потрібно досить часто. Я думаю, що це насправді є загальнодоступним і зараз.
EpicPandaForce

10

Це найпростіше рішення і робота для мене.

1.) ви додаєте свій фрагмент

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

Можливо, буде пізно, але я сподіваюся, що це допоможе комусь іншому, також @CommonsWare опублікував правильну відповідь.

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

9
Це не дозволяє отримати активний фрагмент, оскільки ви не обов'язково знаєте ідентифікатор або тег.
Джастін

7

Можливо, найпростіший спосіб:

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

Це працювало для мене


6

Ви можете створити поле у ​​своєму батьківському класі активності:

public class MainActivity extends AppCompatActivity {

    public Fragment fr;

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

}

А потім всередині кожного класу фрагментів:

public class SomeFragment extends Fragment {

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

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

Ваше поле "fr" - це поточний фрагмент "Об'єкт"

Він також працює з popBackStack ()


4

Я знаю, що минуло деякий час, але я це буду тут, якщо це допоможе комусь.

Правильна відповідь , безумовно , є (і обраний один) один з CommonsWare. У мене виникли ті ж проблеми, що і в наступному

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

зберігається при поверненні null. У моєму xml-файлі моя помилка справді нерозумна:

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

Помилка полягала в тому, що у мене був android: tag INSTEAD OF android: id .


2

@Hammer відповідь працював для мене, я використовую для управління плаваючу кнопку дії

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


1

Якщо ви визначаєте фрагмент у шарі XML діяльності, тоді Activityпереконайтеся, що ви дзвонили setContentView()перед викликом findFragmentById().


1

Якщо ви використовуєте BackStack ... і ТІЛЬКИ, якщо ви використовуєте задній стек, то спробуйте це:

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

Це дасть вам назву поточного класу фрагмента ->

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

0
  1. Зробити перевірку (який фрагмент у контейнері активності) у методі onStart;

    @Override
    protected void onStart() {
    super.onStart();
    Fragment fragmentCurrent = getSupportFragmentManager.findFragmentById(R.id.constraintLayout___activity_main___container);
    }
  2. Деякі перевірки:

    if (fragmentCurrent instanceof MenuFragment) 
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.