Fix Fragment BackStack and Titles
Related to bug #12939786 and bug #13223838
- first use Fragment BreadCrumb for managing Titles and Back
- consider the first fragment as the initial one (both in the
normal case and in the shortcut one)
- fix usage of the Fragment BackStack so that in all cases we
are returning to the initial Fragment before exiting the App.
Change-Id: I96989d14f4e88688747b93ab9fadd96aea214a2c
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 4430138..b7d29fa 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -62,10 +62,8 @@
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
-import android.util.Pair;
import android.util.TypedValue;
import android.util.Xml;
-import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
@@ -200,6 +198,8 @@
private Header mSelectedHeader;
private Header mCurrentHeader;
+ private CharSequence mInitialTitle;
+
// Show only these settings for restricted users
private int[] SETTINGS_FOR_RESTRICTED = {
R.id.wireless_section,
@@ -313,39 +313,6 @@
private final ArrayList<Header> mHeaders = new ArrayList<Header>();
private HeaderAdapter mHeaderAdapter;
- static private class TitlePair extends Pair<Integer, CharSequence> implements Parcelable {
-
- public TitlePair(Integer first, CharSequence second) {
- super(first, second);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(first);
- TextUtils.writeToParcel(second, dest, flags);
- }
-
- TitlePair(Parcel in) {
- super(in.readInt(), TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in));
- }
-
- public static final Creator<TitlePair> CREATOR = new Creator<TitlePair>() {
- public TitlePair createFromParcel(Parcel source) {
- return new TitlePair(source);
- }
- public TitlePair[] newArray(int size) {
- return new TitlePair[size];
- }
- };
- }
-
- private final ArrayList<TitlePair> mTitleStack = new ArrayList<TitlePair>();
-
private DrawerLayout mDrawerLayout;
private ListView mDrawer;
private ActionBarDrawerToggle mDrawerToggle;
@@ -408,7 +375,7 @@
if (isFinishing() || mSelectedHeader == null) {
return;
}
- switchToHeader(mSelectedHeader, false);
+ switchToHeader(mSelectedHeader, false, false);
mSelectedHeader = null;
}
@@ -556,17 +523,8 @@
if (savedInstanceState != null) {
// We are restarting from a previous saved state; used that to
// initialize, instead of starting fresh.
-
- ArrayList<TitlePair> titles =
- savedInstanceState.getParcelableArrayList(SAVE_KEY_TITLES_TAG);
- if (titles != null) {
- mTitleStack.addAll(titles);
- }
- final int lastTitle = mTitleStack.size() - 1;
- if (lastTitle >= 0) {
- final TitlePair last = mTitleStack.get(lastTitle);
- setTitleFromPair(last);
- }
+ mInitialTitle = getTitle();
+ setTitleFromBackStack();
ArrayList<Header> headers =
savedInstanceState.getParcelableArrayList(SAVE_KEY_HEADERS_TAG);
@@ -578,18 +536,15 @@
setSelectedHeader(mHeaders.get(curHeader));
}
}
-
} else {
if (initialFragment != null) {
// If we are just showing a fragment, we want to run in
// new fragment mode, but don't need to compute and show
// the headers.
- switchToHeader(initialFragment, initialArguments, true);
+ final int initialTitleResId = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_TITLE, 0);
+ mInitialTitle = (initialTitleResId > 0) ? getText(initialTitleResId) : getTitle();
- final int initialTitle = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_TITLE, 0);
- if (initialTitle != 0) {
- setTitle(getText(initialTitle));
- }
+ switchToHeader(initialFragment, initialArguments, true, mInitialTitle);
} else {
// We need to try to build the headers.
onBuildHeaders(mHeaders);
@@ -599,7 +554,8 @@
// the currently selected preference fragment.
if (mHeaders.size() > 0) {
Header h = onGetInitialHeader();
- switchToHeader(h, false);
+ mInitialTitle = getHeaderTitle(h);
+ switchToHeader(h, false, true);
}
}
}
@@ -666,32 +622,30 @@
@Override
public void onBackStackChanged() {
- final int count = getFragmentManager().getBackStackEntryCount() + 1;
- TitlePair pair = null;
- int last;
- while (mTitleStack.size() > count) {
- last = mTitleStack.size() - 1;
- pair = mTitleStack.remove(last);
- }
- // Check if we go back
- if (pair != null) {
- int size = mTitleStack.size();
- if (size > 0) {
- last = mTitleStack.size() - 1;
- pair = mTitleStack.get(last);
- setTitleFromPair(pair);
- }
- }
+ setTitleFromBackStack();
}
- private void setTitleFromPair(TitlePair pair) {
- final CharSequence title;
- if (pair.first > 0) {
- title = getText(pair.first);
- } else {
- title = pair.second;
+ private void setTitleFromBackStack() {
+ final int count = getFragmentManager().getBackStackEntryCount();
+ if (count == 0) {
+ setTitle(mInitialTitle);
+ return;
}
- setTitle(title);
+ FragmentManager.BackStackEntry bse = getFragmentManager().getBackStackEntryAt(count - 1);
+ setTitleFromBackStackEntry(bse);
+ }
+
+ private void setTitleFromBackStackEntry(FragmentManager.BackStackEntry bse) {
+ final CharSequence title;
+ final int titleRes = bse.getBreadCrumbTitleRes();
+ if (titleRes > 0) {
+ title = getText(titleRes);
+ } else {
+ title = bse.getBreadCrumbTitle();
+ }
+ if (title != null) {
+ setTitle(title);
+ }
}
/**
@@ -714,10 +668,6 @@
}
}
}
-
- if (mTitleStack.size() > 0) {
- outState.putParcelableList(SAVE_KEY_TITLES_TAG, mTitleStack);
- }
}
@Override
@@ -782,9 +732,10 @@
* preference fragment.
*
* @param header The new header to display.
- * @param validate true means that the fragment's Header needs to be validated
+ * @param validate true means that the fragment's Header needs to be validated.
+ * @param initial true means that it is the initial Header.
*/
- private void switchToHeader(Header header, boolean validate) {
+ private void switchToHeader(Header header, boolean validate, boolean initial) {
if (header == null) {
return;
}
@@ -798,15 +749,11 @@
FragmentManager.POP_BACK_STACK_INCLUSIVE);
} else {
if (header.fragment != null) {
- mTitleStack.clear();
- switchToHeaderInner(header.fragment, header.fragmentArguments, validate);
+ switchToHeaderInner(header.fragment, header.fragmentArguments, validate, !initial,
+ getHeaderTitle(header));
setSelectedHeader(header);
- final TitlePair pair = new TitlePair(0, getHeaderTitle(header));
- mTitleStack.add(pair);
- setTitle(pair.second);
} else if (header.intent != null) {
setSelectedHeader(header);
- mTitleStack.clear();
startActivity(header.intent);
} else {
throw new IllegalStateException(
@@ -860,19 +807,20 @@
}
/**
- * When in two-pane mode, switch the fragment pane to show the given
- * preference fragment.
+ * Switch the fragment pane to show the given preference fragment.
*
* @param fragmentName The name of the fragment to display.
* @param args Optional arguments to supply to the fragment.
* @param validate true means that the fragment's Header needs to be validated
*/
- private void switchToHeader(String fragmentName, Bundle args, boolean validate) {
+ private void switchToHeader(String fragmentName, Bundle args, boolean validate,
+ CharSequence title) {
setSelectedHeader(null);
- switchToHeaderInner(fragmentName, args, validate);
+ switchToHeaderInner(fragmentName, args, validate, false, title);
}
- private void switchToHeaderInner(String fragmentName, Bundle args, boolean validate) {
+ private void switchToHeaderInner(String fragmentName, Bundle args, boolean validate,
+ boolean addToBackStack, CharSequence title) {
getFragmentManager().popBackStack(BACK_STACK_PREFS,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
if (validate && !isValidFragment(fragmentName)) {
@@ -881,8 +829,14 @@
}
Fragment f = Fragment.instantiate(this, fragmentName, args);
FragmentTransaction transaction = getFragmentManager().beginTransaction();
- transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
transaction.replace(R.id.prefs, f);
+ transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
+ if (addToBackStack) {
+ transaction.addToBackStack(BACK_STACK_PREFS);
+ }
+ if (title != null) {
+ transaction.setBreadCrumbTitle(title);
+ }
transaction.commitAllowingStateLoss();
}
@@ -1036,6 +990,13 @@
*/
private void startWithFragment(String fragmentName, Bundle args, Fragment resultTo,
int resultRequestCode, int titleRes, CharSequence titleText) {
+ final CharSequence cs;
+ if (titleRes != 0) {
+ cs = getText(titleRes);
+ } else {
+ cs = titleText;
+ }
+
Fragment f = Fragment.instantiate(this, fragmentName, args);
if (resultTo != null) {
f.setTargetFragment(resultTo, resultRequestCode);
@@ -1044,19 +1005,8 @@
transaction.replace(R.id.prefs, f);
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
transaction.addToBackStack(BACK_STACK_PREFS);
+ transaction.setBreadCrumbTitle(cs);
transaction.commitAllowingStateLoss();
-
- final TitlePair pair;
- final CharSequence cs;
- if (titleRes != 0) {
- pair = new TitlePair(titleRes, null);
- cs = getText(titleRes);
- } else {
- pair = new TitlePair(0, titleText);
- cs = titleText;
- }
- setTitle(cs);
- mTitleStack.add(pair);
}
/**