Как получить отображаемый фрагмент?

Я играю с фрагментами в Android.

Я знаю, что могу изменить фрагмент, используя следующий код:

FragmentManager fragMgr = getSupportFragmentManager();
FragmentTransaction fragTrans = fragMgr.beginTransaction();

MyFragment myFragment = new MyFragment(); //my custom fragment

fragTrans.replace(android.R.id.content, myFragment);
fragTrans.addToBackStack(null);
fragTrans.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
fragTrans.commit();

У меня вопрос в файле Java, как я могу получить отображаемый в данный момент экземпляр фрагмента?

Ответ 1

Когда вы добавляете фрагмент в свою транзакцию, вы должны использовать тег.

fragTrans.replace(android.R.id.content, myFragment, "MY_FRAGMENT");

... и позже, если вы хотите проверить, является ли фрагмент видимым:

MyFragment myFragment = (MyFragment)getFragmentManager().findFragmentByTag("MY_FRAGMENT");
if (myFragment != null && myFragment.isVisible()) {
   // add your code here
}

См. также http://developer.android.com/reference/android/app/Fragment.html

Ответ 2

Я знаю, это старый пост, но раньше у меня тоже были проблемы. Нашел решение, которое должно было сделать это в функции прослушивания onBackStackChanged()

  @Override
    public void onBackPressed() {
        super.onBackPressed();

         Fragment f = getActivity().getFragmentManager().findFragmentById(R.id.fragment_container);
      if(f instanceof CustomFragmentClass) 
        // do something with f
        ((CustomFragmentClass) f).doSomething();

    }

Это сработало для меня, так как я не хотел перебирать каждый фрагмент, чтобы найти видимый. Надеюсь, это поможет кому-то еще.

Ответ 3

Вот мое решение, которое я считаю удобным для сценариев с низким фрагментом

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

Ответ 4

Каждый раз, когда вы показываете фрагмент, вы должны поместить его в backstack:

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setTransition(FragmentTransaction.TRANSIT_ENTER_MASK);       
ft.add(R.id.primaryLayout, fragment, tag);
ft.addToBackStack(tag);
ft.commit();        

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

public BaseFragment getActiveFragment() {
    if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
        return null;
    }
    String tag = getSupportFragmentManager().getBackStackEntryAt(getSupportFragmentManager().getBackStackEntryCount() - 1).getName();
    return (BaseFragment) getSupportFragmentManager().findFragmentByTag(tag);
}

Ответ 5

То, что я использую, чтобы найти текущий отображаемый фрагмент, находится ниже кода. Это просто, и теперь это работает для меня. Он работает в активности, которая содержит фрагменты

    FragmentManager fragManager = this.getSupportFragmentManager();
    int count = this.getSupportFragmentManager().getBackStackEntryCount();
    Fragment frag = fragManager.getFragments().get(count>0?count-1:count);

Ответ 6

reactive:

Observable.from(getSupportFragmentManager().getFragments())
    .filter(fragment -> fragment.isVisible())
    .subscribe(fragment1 -> {
        // Do something with it
    }, throwable1 -> {
        // 
    });

Ответ 7

Мой метод основан на try/catch следующим образом:

MyFragment viewer = null;
    if(getFragmentManager().findFragmentByTag(MY_TAG_FRAGMENT) instanceOf MyFragment){
    viewer = (MyFragment) getFragmentManager().findFragmentByTag(MY_TAG_FRAGMENT);
}

Но может быть лучше...

Ответ 8

Ну, этот вопрос получил много взглядов и внимания, но не содержал самое легкое решение из моего конца - использовать getFragments().

            List fragments = getSupportFragmentManager().getFragments();
            mCurrentFragment = fragments.get(fragments.size() - 1);

Ответ 9

Это немного поздно, но для всех, кто заинтересован: Если вам известен индекс вашего желаемого фрагмента в FragmentManager, просто получите ссылку на него и проверьте функцию isMenuVisible()! здесь:

getSupportFragmentManager().getFragments().get(0).isMenuVisible()

Если true Его видимый для пользователя и т.д.

Ответ 10

1)

ft.replace(R.id.content_frame, fragment, **tag**).commit();

2)

FragmentManager fragmentManager = getSupportFragmentManager();
Fragment currentFragment = fragmentManager.findFragmentById(R.id.content_frame);

3)

if (currentFragment.getTag().equals(**"Fragment_Main"**))
{
 //Do something
}
else
if (currentFragment.getTag().equals(**"Fragment_DM"**))
{
//Do something
}

Ответ 11

Вы можете запросить, какой фрагмент загружен в ваш фрейм контента "Деятельности", и получить класс фрагмента или фрагмент "простое имя" (в виде строки).

public String getCurrentFragment(){
     return activity.getSupportFragmentManager().findFragmentById(R.id.content_frame).getClass().getSimpleName();
}

Использование:

Log.d(TAG, getCurrentFragment());

Выходы:

D/MainActivity: FragOne

Ответ 12

Котлин путь;

val currentFragment = supportFragmentManager.fragments.last()

Ответ 13

Вдохновленный Тайни, ответьте, вот мои два цента. Небольшое изменение от большинства других реализаций.

private Fragment getCurrentFragment() {
    FragmentManager fragmentManager = myActivity.getSupportFragmentManager();
    int stackCount = fragmentManager.getBackStackEntryCount();
    if( fragmentManager.getFragments() != null ) return fragmentManager.getFragments().get( stackCount > 0 ? stackCount-1 : stackCount );
    else return null;
}

Замените "myActivity" на "this", если это ваша текущая деятельность или используйте ссылку на вашу активность.

Ответ 14

Есть метод, называемый findFragmentById() в SupportFragmentManager. Я использую его в контейнере действий, например:

public Fragment currentFragment(){
    return getSupportFragmentManager().findFragmentById(R.id.activity_newsfeed_frame);
}

Как получить текущий Fragment. Если у вас есть пользовательский Fragment и нужно проверить, что это за Fragment, я обычно использую instanceof:

if (currentFragment() instanceof MyFrag){
    // Do something here
}

Ответ 15

Если попасть сюда и вы используете Kotlin:

var fragment = supportFragmentManager.findFragmentById(R.id.fragment_container)

R.id.fragment_container - это id где fragment представляет свою activity

Или, если вы хотите более хорошее решение:

supportFragmentManager.findFragmentById(R.id.content_main)?.let {
    // the fragment exists

    if (it is FooFragment) {
        // The presented fragment is FooFragment type
    }
}

Ответ 16

Ответ Sev работает, когда вы нажимаете кнопку "Назад" или иным образом меняете стоп-память.

Я сделал что-то немного другое. У меня есть функция прослушивателя изменений в backstack на базовом фрагменте и его фрагментах, и этот код находится в слушателе:

Fragment f = getActivity().getSupportFragmentManager().findFragmentById(R.id.container);

if (f.getClass().equals(getClass())) {
    // On back button, or popBackStack(),
    // the fragment that becoming visible executes here,
    // but not the one being popped, or others on the back stack

    // So, for my case, I can change action bar bg color per fragment
}

Ответ 17

Это простой способ получить текущий фрагмент.

getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
  @Override public void onBackStackChanged() {
    currentFragment = fragmentManager.findFragmentById(R.id.content);
    if (currentFragment !=  null && (currentFragment instanceof LoginScreenFragment)) {
      logout.setVisibility(View.GONE);
    } else {
      logout.setVisibility(View.VISIBLE);
    }
  }
});

Ответ 18

Это работа для меня. Надеюсь, что это кому-то поможет.

FragmentManager fragmentManager = this.getSupportFragmentManager();  
        String tag = fragmentManager
                    .getBackStackEntryAt(
                    fragmentManager
                    .getBackStackEntryCount() - 1)
                    .getName();
              Log.d("This is your Top Fragment name: ", ""+tag);

Ответ 19

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

findFragmentByID(R.id.container);

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

Следующий метод не работает. Он просто получает фрагмент с тегом. Не тратьте время на этот метод. Я уверен, что он использует его, но для получения самой последней версии того же фрагмента не является одним из них.

findFragmentByTag()

Ответ 20

Оформить заказ на это решение. Это помогло мне получить текущий фрагмент.

if(getSupportFragmentManager().getBackStackEntryCount() > 0){
        android.support.v4.app.Fragment f = 
         getSupportFragmentManager().findFragmentById(R.id.fragment_container);
        if(f instanceof ProfileFragment){
            Log.d(TAG, "Profile Fragment");
        }else if(f instanceof SavedLocationsFragment){
            Log.d(TAG, "SavedLocations Fragment");
        }else if(f instanceof AddLocationFragment){
            Log.d(TAG, "Add Locations Fragment");
        }

Ответ 21

final FragmentManager fm=this.getSupportFragmentManager();
final Fragment fragment=fm.findFragmentByTag("MY_FRAGMENT");

if(fragment != null && fragment.isVisible()){
      Log.i("TAG","my fragment is visible");
}
else{
      Log.i("TAG","my fragment is not visible");
}

Ответ 22

В основной деятельности метод onAttachFragment (фрагмент фрагмента) вызывается, когда к этому активу присоединяется новый фрагмент. В этом методе вы можете получить экземпляр текущего фрагмента. Тем не менее, метод onAttachFragment не вызывается, когда фрагмент выталкивается с задней стороны, т.е. Когда нажата кнопка "Назад", чтобы получить верхний фрагмент поверх стека. Я все еще ищу метод обратного вызова, который запускается в основном действии, когда фрагмент становится видимым внутри действия.

Ответ 23

У меня возникла аналогичная проблема, где я хотел знать, какой фрагмент был последний раз отображен при нажатии клавиши назад. Я использовал очень простое решение, которое сработало для меня. Каждый раз, когда я открываю фрагмент, в методе onCreate() я устанавливаю переменную в моем одиночном элементе (заменим "myFragment" на имя вашего фрагмента)

MySingleton.currentFragment = myFragment.class;

Переменная объявляется в singleton как

public static Class currentFragment = null; 

Затем в onBackPressed() я проверяю

    if (MySingleton.currentFragment == myFragment.class){
        // do something
        return;
    }
    super.onBackPressed();

Обязательно вызовите super.onBackPressed(); после "возврата", иначе приложение обработает обратный ключ, который в моем случае заставил приложение завершить работу.

Ответ 24

В случае прокручиваемых фрагментов, когда вы используете экземпляр класса ViewPager, предположим, mVeiwPager, вы можете вызвать mViewPager.getCurrentItem() для получения текущего номера int фрагмента.

в MainLayout.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:orientation="vertical"
    tools:context="unidesign.photo360.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="false"
        android:theme="@style/AppTheme.AppBarOverlay"
        app:expanded="false">

        <android.support.v7.widget.Toolbar
            android:id="@+id/main_activity_toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            app:popupTheme="@style/AppTheme.PopupOverlay"
            app:title="@string/app_name">

        </android.support.v7.widget.Toolbar>

    </android.support.design.widget.AppBarLayout>


    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    </android.support.v4.view.ViewPager>
    
</android.support.design.widget.CoordinatorLayout>

Ответ 25

getSupportFragmentManager().findFragmentById(R.id.content_frame).getClass().getSimpleName();

Ну, я думаю, это самый прямой ответ на этот вопрос. Надеюсь, это поможет.

Ответ 26

Вот решение Kotlin:

if ( this.getSupportFragmentManager().getBackStackEntryCount()>0 ) {
    var fgmt = this.getSupportFragmentManager().fragments[this.getSupportFragmentManager().getBackStackEntryCount()-1]
    if( fgmt is FgmtClassName ) {
        (fgmt as FgmtClassName).doSth()
    }
}

Упрощенный способ:

with ( this.getSupportFragmentManager() ) {
    if ( getBackStackEntryCount()>0 ) {
        var fgmt = fragments[getBackStackEntryCount()-1]
        if ( fgmt is FgmtClassName ) {
            (fgmt as FgmtClassName).doSth()
        }
    }
}

Ответ 27

Если вы используете библиотеку поддержки v13, эта проблема исправлена, и вы должны просто переопределить:

@Override
public void setUserVisibleHint(boolean isVisibleToUser)
{
    // TODO Auto-generated method stub
    super.setUserVisibleHint(isVisibleToUser);
}

Дело в том, что вы не можете их смешивать, потому что фрагмент не совместим с классом фрагментов версии 4.

Если вы этого не сделали, и вы используете библиотеку поддержки V4, переопределите метод setPrimaryItem для вашего FragmentStatePagerAdapter.

Я использовал это, чтобы обновить заголовок Actionbat в больших списках.

Ответ 28

Возможно, самый простой способ:

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

Это сработало для меня

Ответ 29

Использование шины событий (например Otto, EventBus или RxJava Bus) особенно удобно в этих ситуациях.

Хотя этот подход не обязательно передает вам видимый в данный момент фрагмент как объект (хотя это тоже можно сделать, но это приводит к более длинной цепочке вызовов), он позволяет выполнять действия над видимым в данный момент фрагментом (который обычно то, что вы хотите знать, в настоящее время видимый фрагмент).

  • убедитесь, что вы соблюдаете жизненный цикл фрагмента и регистрируете/отменяете регистрацию шины событий в соответствующее время.
  • в точке, где вам нужно знать текущий видимый фрагмент и выполнить набор действий. снимать событие с шиной событий.

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

Ответ 30

Немного странно, но я посмотрел на FragmentManager $FragmentManagerImpl, и для меня работает следующее:

public static Fragment getActiveFragment(Activity activity, int index)
{
    Bundle bundle = new Bundle();
    String key = "i";
    bundle.putInt(key,index);
    Fragment fragment=null;
    try
    {
        fragment = activity.getFragmentManager().getFragment(bundle, key);
    } catch(Exception e){}
    return fragment;
}

чтобы первый активный фрагмент использовал 0 в качестве индекса