Подтвердить что ты не робот

Получить последний фрагмент в backstack

Как я могу получить последний экземпляр фрагмента, добавленный в backstack (если я не знаю тег фрагмента и id)?

FragmentManager fragManager = activity.getSupportFragmentManager();
FragmentTransaction fragTransacion = fragMgr.beginTransaction();

/****After add , replace fragments 
  (some of the fragments are add to backstack , some are not)***/

//HERE, How can I get the latest added fragment from backstack ??
4b9b3361

Ответ 1

Вы можете использовать метод getName() FragmentManager.BackStackEntry, который был введен в API-уровень 14. Этот метод вернет тег, который использовался вами, когда вы добавили фрагмент в backstack с помощью addTobackStack(tag).

int index = getActivity().getFragmentManager().getBackStackEntryCount() - 1
FragmentManager.BackStackEntry backEntry = getFragmentManager().getBackStackEntryAt(index);
String tag = backEntry.getName();
Fragment fragment = getFragmentManager().findFragmentByTag(tag);

Вам нужно убедиться, что вы добавили фрагмент в заднюю часть, например:

fragmentTransaction.addToBackStack(tag);

Ответ 2

FragmentManager.findFragmentById(fragmentsContainerId) 

функция возвращает ссылку вверху Fragment в backstack. Пример использования:

    fragmentManager.addOnBackStackChangedListener(new OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
            Fragment fr = fragmentManager.findFragmentById(R.id.fragmentsContainer);
            if(fr!=null){
                Log.e("fragment=", fr.getClass().getSimpleName());
            }
        }
    });

Ответ 3

I personnaly попробовал многие из этих решений и закончил с этим рабочим решением:

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

protected int getFragmentCount() {
    return getSupportFragmentManager().getBackStackEntryCount();
}

Затем, когда вы добавляете/заменяете свой фрагмент с помощью метода FragmentTransaction, генерируйте уникальный фрагмент для вашего фрагмента (например: используя количество фрагментов в вашем стеке):

getSupportFragmentManager().beginTransaction().add(yourContainerId, yourFragment, Integer.toString(getFragmentCount()));

Наконец, вы можете найти любой из своих фрагментов в своей задней части с помощью этого метода:

private Fragment getFragmentAt(int index) {
    return getFragmentCount() > 0 ? getSupportFragmentManager().findFragmentByTag(Integer.toString(index)) : null;
}

Следовательно, выбор верхнего фрагмента в вашей задней части может быть легко достигнут, вызвав:

protected Fragment getCurrentFragment() {
    return getFragmentAt(getFragmentCount() - 1);
}

Надеюсь, это поможет!

Ответ 4

В фрагментаторе есть список фрагментов. Имейте в виду, что удаление фрагмента не уменьшает размер списка (запись фрагмента превращается в нуль). Поэтому допустимым решением было бы следующее:

public Fragment getTopFragment() {
 List<Fragment> fragentList = fragmentManager.getFragments();
 Fragment top = null;
  for (int i = fragentList.size() -1; i>=0 ; i--) {
   top = (Fragment) fragentList.get(i);
     if (top != null) {
       return top;
     }
   }
 return top;
}

Ответ 5

Ответ, данный deepak goel, не работает для меня, потому что я всегда получаю null от entry.getName();

Что я делаю, так это установить тег на фрагмент следующим образом:

ft.add(R.id.fragment_container, fragmentIn, FRAGMENT_TAG);

Где ft - моя транзакция фрагмента, а FRAGMENT_TAG - тег. Затем я использую этот код для получения фрагмента:

Fragment prev_fragment = fragmentManager.findFragmentByTag(FRAGMENT_TAG);

Ответ 6

Сохраните свой собственный задний стек: myBackStack. Как вы Add фрагмент для FragmentManager, также добавьте его в myBackStack. В onBackStackChanged() поп из myBackStack, когда его длина больше, чем getBackStackEntryCount.

Ответ 7

вы можете использовать getBackStackEntryAt(). Чтобы узнать, сколько записей в операции выполняется в backstack, вы можете использовать getBackStackEntryCount()

int lastFragmentCount = getBackStackEntryCount() - 1;

Ответ 8

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

Если вы действительно хотите иметь стек фрагментов и иметь доступ к фрагменту по его индексу в стеке, вам лучше иметь слой абстракции над FragmentManager и его backstack. Вот как вы можете это сделать:

public class FragmentStackManager {
  private final FragmentManager fragmentManager;
  private final int containerId;

  private final List<Fragment> fragments = new ArrayList<>();

  public FragmentStackManager(final FragmentManager fragmentManager,
      final int containerId) {
    this.fragmentManager = fragmentManager;
    this.containerId = containerId;
  }

  public Parcelable saveState() {
    final Bundle state = new Bundle(fragments.size());
    for (int i = 0, count = fragments.size(); i < count; ++i) {
      fragmentManager.putFragment(state, Integer.toString(i), fragments.get(i));
    }
    return state;
  }

  public void restoreState(final Parcelable state) {
    if (state instanceof Bundle) {
      final Bundle bundle = (Bundle) state;
      int index = 0;
      while (true) {
        final Fragment fragment =
            fragmentManager.getFragment(bundle, Integer.toString(index));
        if (fragment == null) {
          break;
        }

        fragments.add(fragment);
        index += 1;
      }
    }
  }

  public void replace(final Fragment fragment) {
    fragmentManager.popBackStackImmediate(
        null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
    fragmentManager.beginTransaction()
        .replace(containerId, fragment)
        .addToBackStack(null)
        .commit();
    fragmentManager.executePendingTransactions();

    fragments.clear();
    fragments.add(fragment);
  }

  public void push(final Fragment fragment) {
    fragmentManager
        .beginTransaction()
        .replace(containerId, fragment)
        .addToBackStack(null)
        .commit();
    fragmentManager.executePendingTransactions();

    fragments.add(fragment);
  }

  public boolean pop() {
    if (isEmpty()) {
      return false;
    }

    fragmentManager.popBackStackImmediate();

    fragments.remove(fragments.size() - 1);
    return true;
  }

  public boolean isEmpty() {
    return fragments.isEmpty();
  }

  public int size() {
    return fragments.size();
  }

  public Fragment getFragment(final int index) {
    return fragments.get(index);
  }
}

Теперь вместо добавления и удаления фрагментов, вызвав непосредственно FragmentManager, вы должны использовать методы push(), replace() и pop() FragmentStackManager. И вы сможете получить доступ к самому верхнему фрагменту, просто позвонив stack.get(stack.size() - 1).

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

Первый взлом - это просто, чтобы все активные фрагменты были добавлены в диспетчер фрагментов. Если вы просто замените фрагменты один за другим и вытащите из стека, этот метод вернет самый верхний фрагмент:

public class BackStackHelper {
  public static List<Fragment> getTopFragments(
      final FragmentManager fragmentManager) {
    final List<Fragment> fragments = fragmentManager.getFragments();
    final List<Fragment> topFragments = new ArrayList<>();

    for (final Fragment fragment : fragments) {
      if (fragment != null && fragment.isResumed()) {
        topFragments.add(fragment);
      }
    }

    return topFragments;
  }
}

Второй подход - это событие более хакерское и позволяет получить все фрагменты, добавленные в последнюю транзакцию, для которой был вызван addToBackStack:

package android.support.v4.app;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class BackStackHelper {
  public static List<Fragment> getTopFragments(
      final FragmentManager fragmentManager) {
    if (fragmentManager.getBackStackEntryCount() == 0) {
      return Collections.emptyList();
    }

    final List<Fragment> fragments = new ArrayList<>();

    final int count = fragmentManager.getBackStackEntryCount();
    final BackStackRecord record =
        (BackStackRecord) fragmentManager.getBackStackEntryAt(count - 1);
    BackStackRecord.Op op = record.mHead;
    while (op != null) {
      switch (op.cmd) {
        case BackStackRecord.OP_ADD:
        case BackStackRecord.OP_REPLACE:
        case BackStackRecord.OP_SHOW:
        case BackStackRecord.OP_ATTACH:
          fragments.add(op.fragment);
      }
      op = op.next;
    }

    return fragments;
  }
}

Обратите внимание, что в этом случае вы должны поместить этот класс в пакет android.support.v4.app.

Ответ 9

Или вы можете просто добавить тег при добавлении фрагментов, соответствующих их содержимому, и использовать простое статическое поле String (также вы можете сохранить его в наборе экземпляров активности в методе onSaveInstanceState (Bundle)), чтобы сохранить последний добавленный тег фрагмента и получить этот фрагмент byTag() в любое время, когда вам нужно...

Ответ 10

Самый высокий (Deepak Goel) ответ не помог мне. Каким-то образом тег не был добавлен должным образом.

В итоге я просто отправил идентификатор фрагмента через поток (используя намерения) и извлек его непосредственно из диспетчера фрагментов.

Ответ 11

этот вспомогательный метод получает фрагмент сверху стека:

public Fragment getTopFragment() {
if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
    return null;
}
String fragmentTag = getSupportFragmentManager().getBackStackEntryAt(getSupportFragmentManager().getBackStackEntryCount() - 1).getName();
return getSupportFragmentManager().findFragmentByTag(fragmentTag);

}

Ответ 12

Просто взял @roghayeh hosseini (правильный) ответ и сделал его в Котлине для тех, кто здесь, в 2017 году:)

fun getTopFragment(): Fragment? {
    supportFragmentManager.run {
        return when (backStackEntryCount) {
            0 -> null
            else -> findFragmentByTag(getBackStackEntryAt(backStackEntryCount - 1).name)
        }
    }
}

* Это должно вызываться изнутри Activity.

Наслаждайтесь:)