There are several painful issues with the initial CL. Doing a revert for now and will rework this.
Revert "Fix bug #12939786 BACK should go back into the Fragments BackStack and finally to Overview ...and then exit the Settings App"
This reverts commit 4cc95a53c2d9080095c4e1e06f815b8bc7a2cdfe.
Change-Id: Iaa21d4771d0b004eff3d8e68b91b546a633d8f23
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 8bfde06..af0d8bb 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -70,6 +70,7 @@
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
+import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
@@ -399,7 +400,7 @@
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mDrawerLayout.closeDrawer(mDrawer);
- onListItemClick((ListView) parent, view, position, id);
+ onListItemClick((ListView)parent, view, position, id);
}
}
@@ -516,6 +517,7 @@
mDrawer = (ListView) findViewById(R.id.headers_drawer);
mDrawer.setAdapter(mHeaderAdapter);
mDrawer.setOnItemClickListener(new DrawerItemClickListener());
+ mDrawer.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close);
@@ -538,23 +540,31 @@
}
} else {
- // We need to first to build the headers.
- onBuildHeaders(mHeaders);
-
- final CharSequence initialTitle = getTitle();
-
- // If there are headers, get the initial fragment and push it first so that pressing
- // BACK will always go to it before exiting the app
- if (mHeaders.size() > 0) {
- switchToHeader(mFirstHeader, false, true);
- }
-
- // Got to the initial fragment if one is specified
if (initialFragment != null) {
- final int initialTitleRes = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_TITLE, 0);
- final Header h =
- onGetInitialHeader(initialTitle, initialTitleRes, initialArguments);
- switchToHeader(h, false, false);
+ // 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 initialTitle = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_TITLE, 0);
+ if (initialTitle != 0) {
+ setTitle(getText(initialTitle));
+ }
+ } else {
+ // We need to try to build the headers.
+ onBuildHeaders(mHeaders);
+
+ // If there are headers, then at this point we need to show
+ // them and, depending on the screen, we may also show in-line
+ // the currently selected preference fragment.
+ if (mHeaders.size() > 0) {
+ if (initialFragment == null) {
+ Header h = onGetInitialHeader();
+ switchToHeader(h, false);
+ } else {
+ switchToHeader(initialFragment, initialArguments, false);
+ }
+ }
}
}
@@ -625,7 +635,7 @@
@Override
public void onBackStackChanged() {
- final int count = getFragmentManager().getBackStackEntryCount();
+ final int count = getFragmentManager().getBackStackEntryCount() + 1;
TitlePair pair = null;
int last;
while (mTitleStack.size() > count) {
@@ -647,9 +657,6 @@
}
setTitle(title);
}
- } else {
- final String title = getResources().getString(R.string.settings_label);
- setTitle(title);
}
}
}
@@ -739,18 +746,20 @@
* preference fragment.
*
* @param header The new header to display.
- * @param validate true means that the fragment's Header needs to be validated.
- * @param initial true means that the fragment is the initial one.
+ * @param validate true means that the fragment's Header needs to be validated
*/
- private void switchToHeader(Header header, boolean validate, boolean initial) {
- if (mCurHeader != header) {
+ private void switchToHeader(Header header, boolean validate) {
+ if (mCurHeader == header) {
+ // This is the header we are currently displaying. Just make sure
+ // to pop the stack up to its root state.
+ getFragmentManager().popBackStack(BACK_STACK_PREFS,
+ FragmentManager.POP_BACK_STACK_INCLUSIVE);
+ } else {
+ mTitleStack.clear();
if (header.fragment == null) {
throw new IllegalStateException("can't switch to header that has no fragment");
}
- getFragmentManager().popBackStackImmediate(BACK_STACK_PREFS,
- FragmentManager.POP_BACK_STACK_INCLUSIVE);
- mTitleStack.clear();
- switchToHeaderInner(header.fragment, header.fragmentArguments, validate, !initial);
+ switchToHeaderInner(header.fragment, header.fragmentArguments, validate);
setSelectedHeader(header);
final CharSequence title;
if (header.fragment.equals("com.android.settings.dashboard.DashboardSummary")) {
@@ -776,116 +785,44 @@
}
}
- public Header onGetInitialHeader(CharSequence title, int titleRes, Bundle args) {
+ public Header onGetInitialHeader() {
String fragmentClass = getStartingFragmentClass(super.getIntent());
if (fragmentClass != null) {
Header header = new Header();
header.fragment = fragmentClass;
- header.title = title;
- header.titleRes = titleRes;
- header.fragmentArguments = args;
+ header.title = getTitle();
+ header.fragmentArguments = getIntent().getExtras();
mCurrentHeader = header;
return header;
}
+
return mFirstHeader;
}
- private void switchToHeaderInner(String fragmentName, Bundle args, boolean validate,
- boolean addToBackStack) {
+ /**
+ * When in two-pane mode, 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) {
+ setSelectedHeader(null);
+ switchToHeaderInner(fragmentName, args, validate);
+ }
+
+ private void switchToHeaderInner(String fragmentName, Bundle args, boolean validate) {
+ getFragmentManager().popBackStack(BACK_STACK_PREFS,
+ FragmentManager.POP_BACK_STACK_INCLUSIVE);
if (validate && !isValidFragment(fragmentName)) {
throw new IllegalArgumentException("Invalid fragment for this activity: "
+ fragmentName);
}
Fragment f = Fragment.instantiate(this, fragmentName, args);
FragmentTransaction transaction = getFragmentManager().beginTransaction();
- transaction.replace(R.id.prefs, f);
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
- if (addToBackStack) {
- transaction.addToBackStack(BACK_STACK_PREFS);
- }
- transaction.commitAllowingStateLoss();
- }
-
- /**
- * Start a new fragment.
- *
- * @param fragmentName The name of the fragment to display.
- * @param args Optional arguments to supply to the fragment.
- * @param resultTo Option fragment that should receive the result of
- * the activity launch.
- * @param resultRequestCode If resultTo is non-null, this is the request code in which to
- * report the result.
- * @param titleRes Resource ID of string to display for the title of. If the Resource ID is a
- * valid one then it will be used to get the title. Otherwise the titleText
- * argument will be used as the title.
- * @param titleText string to display for the title of.
- */
- private void startWithFragment(String fragmentName, Bundle args, Fragment resultTo,
- int resultRequestCode, int titleRes, CharSequence titleText) {
- Fragment f = Fragment.instantiate(this, fragmentName, args);
- if (resultTo != null) {
- f.setTargetFragment(resultTo, resultRequestCode);
- }
- FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.prefs, f);
- transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
- transaction.addToBackStack(BACK_STACK_PREFS);
- 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);
- }
-
- /**
- * Start a new fragment containing a preference panel. If the preferences
- * are being displayed in multi-pane mode, the given fragment class will
- * be instantiated and placed in the appropriate pane. If running in
- * single-pane mode, a new activity will be launched in which to show the
- * fragment.
- *
- * @param fragmentClass Full name of the class implementing the fragment.
- * @param args Any desired arguments to supply to the fragment.
- * @param titleRes Optional resource identifier of the title of this
- * fragment.
- * @param titleText Optional text of the title of this fragment.
- * @param resultTo Optional fragment that result data should be sent to.
- * If non-null, resultTo.onActivityResult() will be called when this
- * preference panel is done. The launched panel must use
- * {@link #finishPreferencePanel(Fragment, int, Intent)} when done.
- * @param resultRequestCode If resultTo is non-null, this is the caller's
- * request code to be received with the resut.
- */
- public void startPreferencePanel(String fragmentClass, Bundle args, int titleRes,
- CharSequence titleText, Fragment resultTo,
- int resultRequestCode) {
- startWithFragment(fragmentClass, args, resultTo, resultRequestCode, titleRes, titleText);
- }
-
- /**
- * Start a new fragment.
- *
- * @param fragment The fragment to start
- * @param push If true, the current fragment will be pushed onto the back stack. If false,
- * the current fragment will be replaced.
- */
- public void startPreferenceFragment(Fragment fragment, boolean push) {
- FragmentTransaction transaction = getFragmentManager().beginTransaction();
- transaction.replace(R.id.prefs, fragment);
- if (push) {
- transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
- transaction.addToBackStack(BACK_STACK_PREFS);
- } else {
- transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
- }
transaction.commitAllowingStateLoss();
}
@@ -967,6 +904,31 @@
}
/**
+ * Start a new fragment containing a preference panel. If the preferences
+ * are being displayed in multi-pane mode, the given fragment class will
+ * be instantiated and placed in the appropriate pane. If running in
+ * single-pane mode, a new activity will be launched in which to show the
+ * fragment.
+ *
+ * @param fragmentClass Full name of the class implementing the fragment.
+ * @param args Any desired arguments to supply to the fragment.
+ * @param titleRes Optional resource identifier of the title of this
+ * fragment.
+ * @param titleText Optional text of the title of this fragment.
+ * @param resultTo Optional fragment that result data should be sent to.
+ * If non-null, resultTo.onActivityResult() will be called when this
+ * preference panel is done. The launched panel must use
+ * {@link #finishPreferencePanel(Fragment, int, Intent)} when done.
+ * @param resultRequestCode If resultTo is non-null, this is the caller's
+ * request code to be received with the resut.
+ */
+ public void startPreferencePanel(String fragmentClass, Bundle args, int titleRes,
+ CharSequence titleText, Fragment resultTo,
+ int resultRequestCode) {
+ startWithFragment(fragmentClass, args, resultTo, resultRequestCode, titleRes, titleText);
+ }
+
+ /**
* Called by a preference panel fragment to finish itself.
*
* @param caller The fragment that is asking to be finished.
@@ -980,6 +942,64 @@
}
/**
+ * Start a new fragment.
+ *
+ * @param fragment The fragment to start
+ * @param push If true, the current fragment will be pushed onto the back stack. If false,
+ * the current fragment will be replaced.
+ */
+ public void startPreferenceFragment(Fragment fragment, boolean push) {
+ FragmentTransaction transaction = getFragmentManager().beginTransaction();
+ transaction.replace(R.id.prefs, fragment);
+ if (push) {
+ transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
+ transaction.addToBackStack(BACK_STACK_PREFS);
+ } else {
+ transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
+ }
+ transaction.commitAllowingStateLoss();
+ }
+
+ /**
+ * Start a new fragment.
+ *
+ * @param fragmentName The name of the fragment to display.
+ * @param args Optional arguments to supply to the fragment.
+ * @param resultTo Option fragment that should receive the result of
+ * the activity launch.
+ * @param resultRequestCode If resultTo is non-null, this is the request code in which to
+ * report the result.
+ * @param titleRes Resource ID of string to display for the title of. If the Resource ID is a
+ * valid one then it will be used to get the title. Otherwise the titleText
+ * argument will be used as the title.
+ * @param titleText string to display for the title of.
+ */
+ private void startWithFragment(String fragmentName, Bundle args, Fragment resultTo,
+ int resultRequestCode, int titleRes, CharSequence titleText) {
+ Fragment f = Fragment.instantiate(this, fragmentName, args);
+ if (resultTo != null) {
+ f.setTargetFragment(resultTo, resultRequestCode);
+ }
+ FragmentTransaction transaction = getFragmentManager().beginTransaction();
+ transaction.replace(R.id.prefs, f);
+ transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
+ transaction.addToBackStack(BACK_STACK_PREFS);
+ 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);
+ }
+
+ /**
* Called when the activity needs its list of headers build. By
* implementing this and adding at least one item to the list, you
* will cause the activity to run in its modern fragment mode. Note
@@ -1572,7 +1592,7 @@
* Called when the user selects an item in the header list. The default
* implementation will call either
* {@link #startWithFragment(String, android.os.Bundle, android.app.Fragment, int, int, CharSequence)}
- * or {@link #switchToHeader(com.android.settings.SettingsActivity.Header, boolean, boolean)}
+ * or {@link #switchToHeader(com.android.settings.SettingsActivity.Header, boolean)}
* as appropriate.
*
* @param header The header that was selected.
@@ -1580,7 +1600,7 @@
private void onHeaderClick(Header header) {
if (header == null) return;
if (header.fragment != null) {
- switchToHeader(header, false, false);
+ switchToHeader(header, false);
} else if (header.intent != null) {
startActivity(header.intent);
}