把最新的片段放回去

如何将最新的片段实例添加到堆栈中(如果我不知道片段标记和 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 ??
145614 次浏览

你可以使用 GetBackStackEntryAt ()。为了知道该活动在回栈中保存了多少条目,可以使用 GetBackStackEntryCount ()

int lastFragmentCount = getBackStackEntryCount() - 1;

您可以使用在 API 级别14中引入的 FragmentManager.BackStackEntrygetName()方法。这个方法将返回一个标记,这个标记是您在使用 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);

迪帕克戈尔给出的答案对我不起作用,因为我总是从 entry.getName()得到零;

我要做的就是这样为片段设置一个 Tag:

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

其中 ft 是我的片段事务,FRAGMENT_TAG是标记:

Fragment prev_fragment = fragmentManager.findFragmentByTag(FRAGMENT_TAG);
FragmentManager.findFragmentById(fragmentsContainerId)

函数 返回回栈顶部 Fragment的链接。使用方法示例:

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

保留你自己的备份栈: myBackStack。当你把 Add片段加到 FragmentManager时,也把它加到 myBackStack。在 onBackStackChanged()中,当 myBackStack的长度大于 getBackStackEntryCount时从 myBackStack中弹出。

Or you may just add a tag when adding fragments corresponding to their content and use simple static String field (also you may save it in activity instance bundle in onSaveInstanceState(Bundle) method) to hold last added fragment tag and get this fragment byTag() at any time you need...

我个人尝试了许多这样的解决方案,最终得到了这样一个有效的解决方案:

添加这个实用的方法,将使用下面的几次,以获得在您的回栈片段的数量:

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

Hope this helps!

在碎片 Mananger 中有一个片段列表。请注意,删除一个片段并不会使列表大小减小(片段条目只是变为空)。因此,一个有效的解决方案是:

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

实际上,没有最新的片段添加到堆栈中,因为您可以在单个事务中向堆栈添加几个或多个片段,或者只是删除片段而不添加新的片段。

如果你真的想拥有一个片段堆栈,并且能够通过它在堆栈中的索引访问一个片段,那么你最好在 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);
}
}

现在,您应该使用 FragmentStackManagerpush()replace()pop()方法,而不是通过直接调用 FragmentManager来添加和删除片段。你只要调用 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;
}
}

Please notice that in this case you have to put this class into android.support.v4.app package.

The highest (Deepak Goel) answer didn't work well for me. Somehow the tag wasn't added properly.

最后,我只是通过流(使用意图)发送片段的 ID,并直接从片段管理器检索它。

这个 helper 方法从堆栈顶部获取片段:

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

2017年,他们在 Kotlin 用@roghayeh hosseini (正确)回答了这个问题:)

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

* 这应该从活动内部调用。

享受:)

看起来有些东西变得更好了,因为下面的代码对我来说非常完美,但是我没有在已经提供的答案中找到它。

科特林:

supportFragmentManager.fragments[supportFragmentManager.fragments.size - 1]

Java:

getSupportFragmentManager().getFragments()
.get(getSupportFragmentManager().getFragments().size() - 1)

Kotlin

// In activities
activity.supportFragmentManager.fragments.lastOrNull()


// In fragments
fragment.childFragmentManager.fragments.lastOrNull()

如果使用 addToBackStack(),则可以使用以下代码。

List<Fragment> fragments = fragmentManager.getFragments(); ActiveFragment = fragments.get (fragments.size ()-1) ;

我将向 Deepak Goel 的回答添加一些内容,因为包括我在内的许多人使用他的方法得到了 null。显然,为了让标记在向回栈中添加片段时能够正常工作,应该这样做:

getSupportFragmentManager.beginTransaction().replace(R.id.container_id,FragmentName,TAG_NAME).addToBackStack(TAG_NAME).commit();

您需要将相同的标记添加两次。

我本想评论的,但我没有50个名声。

Kotlin Developers 可以使用它来获取当前的片段:

        supportFragmentManager.addOnBackStackChangedListener {
val myFragment = supportFragmentManager.fragments.last()


if (null != myFragment && myFragment is HomeFragment) {
//HomeFragment is visible or currently loaded
} else {
//your code
}
}