With Android 4.2, the support library got support for nested fragments see here. I\'ve played around with it and found an interesting behaviour / bug regarding back stack an
More than 5 years and this issue is still relevant. If you do not want to use the fragmentManager.getFragments() due to its restriction. Extend and use the below classes:
NestedFragmentActivity.java
abstract public class NestedFragmentActivity extends AppCompatActivity {
private final Stack mActiveFragmentIdStack = new Stack<>();
private final Stack mActiveFragmentTagStack = new Stack<>();
@Override
public void onBackPressed() {
if (mActiveFragmentIdStack.size() > 0 && mActiveFragmentTagStack.size() > 0) {
// Find by id
int lastFragmentId = mActiveFragmentIdStack.lastElement();
NestedFragment nestedFragment = (NestedFragment) getSupportFragmentManager().findFragmentById(lastFragmentId);
// If cannot find by id, find by tag
if (nestedFragment == null) {
String lastFragmentTag = mActiveFragmentTagStack.lastElement();
nestedFragment = (NestedFragment) getSupportFragmentManager().findFragmentByTag(lastFragmentTag);
}
if (nestedFragment != null) {
nestedFragment.onBackPressed();
}
// If cannot find by tag, then simply pop
mActiveFragmentTagStack.pop();
mActiveFragmentIdStack.pop();
} else {
super.onBackPressed();
}
}
public void addToBackStack(int fragmentId, String fragmentTag) {
mActiveFragmentIdStack.add(fragmentId);
mActiveFragmentTagStack.add(fragmentTag);
}
}
NestedFragment.java
abstract public class NestedFragment extends Fragment {
private final Stack mActiveFragmentIdStack = new Stack<>();
private final Stack mActiveFragmentTagStack = new Stack<>();
private NestedFragmentActivity mParentActivity;
private NestedFragment mParentFragment;
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (getParentFragment() == null) {
try {
mParentActivity = (NestedFragmentActivity) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString()
+ " must implement " + NestedFragmentActivity.class.getName());
}
} else {
try {
mParentFragment = (NestedFragment) getParentFragment();
} catch (ClassCastException e) {
throw new ClassCastException(getParentFragment().getClass().toString()
+ " must implement " + NestedFragment.class.getName());
}
}
}
public void onBackPressed() {
if (mActiveFragmentIdStack.size() > 0 && mActiveFragmentTagStack.size() > 0) {
// Find by id
int lastFragmentId = mActiveFragmentIdStack.lastElement();
NestedFragment nestedFragment = (NestedFragment) getChildFragmentManager().findFragmentById(lastFragmentId);
// If cannot find by id, find by tag
if (nestedFragment == null) {
String lastFragmentTag = mActiveFragmentTagStack.lastElement();
nestedFragment = (NestedFragment) getChildFragmentManager().findFragmentByTag(lastFragmentTag);
}
if (nestedFragment != null) {
nestedFragment.onBackPressed();
}
// If cannot find by tag, then simply pop
mActiveFragmentIdStack.pop();
mActiveFragmentTagStack.pop();
} else {
getChildFragmentManager().popBackStack();
}
}
private void addToBackStack(int fragmentId, String fragmentTag) {
mActiveFragmentIdStack.add(fragmentId);
mActiveFragmentTagStack.add(fragmentTag);
}
public void addToParentBackStack() {
if (mParentFragment != null) {
mParentFragment.addToBackStack(getId(), getTag());
} else if (mParentActivity != null) {
mParentActivity.addToBackStack(getId(), getTag());
}
}
}
Explanation:
Each activity and fragment extended from the above classes manages their own back stack for each of their children, and children's children, and so on. The backstack is simply a record of "active fragment" tags/ids. So the caveat is to always provide a tag and/or id for your fragment.
When adding to the backstack in a childFragmentManager, you will need to also call "addToParentBackStack()". This ensures that the fragment's tag/id is added in the parent fragment/activity for later pops.
Example:
getChildFragmentManager().beginTransaction().replace(
R.id.fragment,
fragment,
fragment.getTag()
).addToBackStack(null).commit();
addToParentBackStack();