Получить текущий фрагмент объекта

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.

Лабиб Панампуллан
источник
Связанные - stackoverflow.com/a/21104084/80428
Джей Уик
Помогает ли вам ответ @CommonsWare, потому что я все еще получаю ноль?
IntoTheDeep

Ответы:

253

Теперь в какой-то момент мне нужно определить, какой объект в настоящее время там

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

CommonsWare
источник
1
Спасибо за ваш ответ. Это будет работать, если мы установили фрагмент с помощью fragmentTransaction.replace или, fragmentTransaction.addно не получится, если мы установили его на xml. См. Мое редактирование 2
Labeeb Panampullan
9
@Labeeb P: Вы не можете изменять фрагменты, объявленные в ресурсах макета.
CommonsWare
Создание класса для хранения видимой в данный момент вкладки / фрагмента также будет работать, я просто попробовал это. Надеюсь, что неудач нет.
Skynet
@CommonsWare findFragmentByTagвозвращает ноль в случае ActionBarвкладок. В моем 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);

это даст вам текущий фрагмент, затем вы можете сравнить его с классом фрагмента и выполнить ваши действия.

    if (currentFragment instanceof NameOfYourFragmentClass) {
     Log.v(TAG, "find the current fragment");
  }
молоток
источник
Где поставить эту строку?
Ананд Савьяни
9
Иногда вы должны использовать getSupportFragmentManager()вместо этого, и будет нулевой без 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");

Причина в том, что вы устанавливаете тэг «fragTag» на последний добавленный вами фрагмент (когда вы вызываете replace).

Niqo
источник
Спасибо, я исправил это. Это опечатка при написании этого вопроса. Это будет работать, если мы установили фрагмент с помощью fragmentTransaction.replace или, fragmentTransaction.addно не получится, если мы установили его на xml. См. Мое редактирование 2
Labeeb Panampullan
Спасибо вам большое! Решил мою проблему!
Йонас Грёгер
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;
                }
            }
        }
    }
eluleci
источник
3
Не используйте getFragments()метод. Он помечен @hideи не должен был быть включен в jar библиотеки поддержки. Его не следует рассматривать как часть экспортируемого 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;
}

У меня сработало

madx
источник
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' является текущим фрагментом Object

Работает также с popBackStack ()

buxik
источник
4

Я знаю, что это было давно, но я сделаю это здесь, если это кому-нибудь поможет.

На данный момент правильный ответ (и выбранный) - это ответ CommonsWare. У меня была такая же проблема, как опубликовано, следующее

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

продолжал возвращать ноль. Моя ошибка была действительно глупой, в моем 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: тег INSTEAD OF android: id .

Chayemor
источник
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);
            }
        }
});
Тиаго Мело
источник
2

Если вы выходите из AbstractActivity, вы можете использовать метод getFragments ():

for (Fragment f : getFragments()) {
    if (f instanceof YourClass) {
        // do stuff here
    }
}
Марко Аурелио Алвес Путон
источник
1

Если вы определяете фрагмент в XML-структуре действия, то Activityубедитесь, что вы вызываете setContentView()перед вызовом findFragmentById().

IvancityM
источник
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) 
Владислав Шестернин
источник