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

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

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

Solutions Collecting From Web of "Получить последний фрагмент в backstack"

Вы можете использовать метод 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); 
 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()); } } }); 

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

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

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

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

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

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

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

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

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

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

 Fragment prev_fragment = fragmentManager.findFragmentByTag(FRAGMENT_TAG); 

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

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

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

 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) фрагменту, просто вызвав 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 .

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

 int lastFragmentCount = getBackStackEntryCount() - 1; 

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