The layout of my Android tablet app consists of a list of items and a details view. When a list item is selected the associated content is displayed in the details view.
+--------+-------------+
| Item 1 | |
+--------+ Item |
| Item 2 | details |
+--------+ |
| Item 3 | |
+--------+-------------+
The details view is a Fragment
which is programmatically inflated into a FrameLayout
placeholder:
<FrameLayout
android:id="@+id/detail_fragment_placeholder"
android:layout_width="match_parent"
android:layout_height="match_parent">
Here is the Fragment
operation:
getSupportFragmentManager()
.beginTransaction()
.replace(containerViewId, fragment, fragmentTag)
.addToBackStack(backStackStateName)
.commit();
Multiple instances [Dx]
of the DetailsFragment
are added to the backstack when the user selects one item after another.
[D3]
[D2] [D2]
[D1] -> [D1] -> [D1]
Therefore, the user needs to press the BACK button multiple times to pop the instances from the backstack to empty the details view.
How can I replace an existing instance [Dx]
of DetailsFragment
on the backstack when the fragmentTag
of the existing fragment
matches the fragmentTag
of a new fragment
?
[D1] -> [D2] -> [D3]
I'm not sure I understand your question correctly. If you want to replace multiple fragments with some tag from the top of the backstack with a single fragment with the same tag then you can use the following approach.
Instead of using tags for identifying fragments set different backstack names for fragments of different types. You can still use a fragment tag but it will not help in solving this particular problem. Then remove fragments from the backstack manually one by one until there's a fragment with a different backstack name on the top or no fragments left.
public void addFragment(final int containerViewId, final Fragment fragment,
final String backStackName, final boolean replace) {
final FragmentManager fragmentManager = getSupportFragmentManager();
if (replace) {
while (fragmentManager.getBackStackEntryCount() > 0) {
final int last = fragmentManager.getBackStackEntryCount() - 1;
final FragmentManager.BackStackEntry entry =
fragmentManager.getBackStackEntryAt(last);
if (!TextUtils.equals(entry.getName(), backStackName)) {
break;
}
fragmentManager.popBackStackImmediate();
}
}
fragmentManager
.beginTransaction()
.replace(containerViewId, fragment)
.addToBackStack(backStackName)
.commit();
fragmentManager.executePendingTransactions();
}
Now if you make the following calls your backstack will contain just fragment1
and fragment4
.
addFragment(R.id.container, fragment1, "D2", false);
addFragment(R.id.container, fragment2, "D1", false);
addFragment(R.id.container, fragment3, "D1", false);
addFragment(R.id.container, fragment4, "D1", true);
UPDATE:
In this particular case the following code was enough:
getSupportFragmentManager().popBackStack(
backStackStateName, FragmentManager.POP_BACK_STACK_INCLUSIVE);
getSupportFragmentManager()
.beginTransaction()
.replace(containerViewId, fragment, fragmentTag)
.addToBackStack(backStackStateName)
.commit();