From 4cc95a53c2d9080095c4e1e06f815b8bc7a2cdfe Mon Sep 17 00:00:00 2001 From: Fabrice Di Meglio Date: Fri, 7 Feb 2014 18:53:14 -0800 Subject: [PATCH] Fix bug #12939786 BACK should go back into the Fragments BackStack and finally to Overview ...and then exit the Settings App - fix the way we manage the Fragment BackStack - revert back ChooseLockGeneric to be a PreferenceActivity Change-Id: I3c366b4be606e2e211facd0299b9a2de5cc6ea79 --- .../android/settings/ChooseLockGeneric.java | 3 +- .../android/settings/SettingsActivity.java | 268 ++++++++---------- .../print/PrintServiceSettingsFragment.java | 8 - 3 files changed, 126 insertions(+), 153 deletions(-) diff --git a/src/com/android/settings/ChooseLockGeneric.java b/src/com/android/settings/ChooseLockGeneric.java index a92f5144bcb..6eaf08b90e2 100644 --- a/src/com/android/settings/ChooseLockGeneric.java +++ b/src/com/android/settings/ChooseLockGeneric.java @@ -27,6 +27,7 @@ import android.os.Process; import android.os.UserHandle; import android.os.UserManager; import android.preference.Preference; +import android.preference.PreferenceActivity; import android.preference.PreferenceScreen; import android.security.KeyStore; import android.util.EventLog; @@ -41,7 +42,7 @@ import java.util.List; import libcore.util.MutableBoolean; -public class ChooseLockGeneric extends SettingsActivity { +public class ChooseLockGeneric extends PreferenceActivity { @Override public Intent getIntent() { diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index af0d8bb157b..8bfde063c9a 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -70,7 +70,6 @@ import android.view.MenuItem; 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; @@ -400,7 +399,7 @@ public class SettingsActivity extends Activity @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); } } @@ -517,7 +516,6 @@ public class SettingsActivity extends Activity 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); @@ -540,31 +538,23 @@ public class SettingsActivity extends Activity } } 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) { - // 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); - } - } + final int initialTitleRes = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_TITLE, 0); + final Header h = + onGetInitialHeader(initialTitle, initialTitleRes, initialArguments); + switchToHeader(h, false, false); } } @@ -635,7 +625,7 @@ public class SettingsActivity extends Activity @Override public void onBackStackChanged() { - final int count = getFragmentManager().getBackStackEntryCount() + 1; + final int count = getFragmentManager().getBackStackEntryCount(); TitlePair pair = null; int last; while (mTitleStack.size() > count) { @@ -657,6 +647,9 @@ public class SettingsActivity extends Activity } setTitle(title); } + } else { + final String title = getResources().getString(R.string.settings_label); + setTitle(title); } } } @@ -746,20 +739,18 @@ public class SettingsActivity extends Activity * 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 the fragment is the initial one. */ - 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(); + private void switchToHeader(Header header, boolean validate, boolean initial) { + if (mCurHeader != header) { if (header.fragment == null) { throw new IllegalStateException("can't switch to header that has no fragment"); } - switchToHeaderInner(header.fragment, header.fragmentArguments, validate); + getFragmentManager().popBackStackImmediate(BACK_STACK_PREFS, + FragmentManager.POP_BACK_STACK_INCLUSIVE); + mTitleStack.clear(); + switchToHeaderInner(header.fragment, header.fragmentArguments, validate, !initial); setSelectedHeader(header); final CharSequence title; if (header.fragment.equals("com.android.settings.dashboard.DashboardSummary")) { @@ -785,44 +776,116 @@ public class SettingsActivity extends Activity } } - public Header onGetInitialHeader() { + public Header onGetInitialHeader(CharSequence title, int titleRes, Bundle args) { String fragmentClass = getStartingFragmentClass(super.getIntent()); if (fragmentClass != null) { Header header = new Header(); header.fragment = fragmentClass; - header.title = getTitle(); - header.fragmentArguments = getIntent().getExtras(); + header.title = title; + header.titleRes = titleRes; + header.fragmentArguments = args; mCurrentHeader = header; return header; } - return mFirstHeader; } - /** - * 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); + private void switchToHeaderInner(String fragmentName, Bundle args, boolean validate, + boolean addToBackStack) { 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.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE); 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(); } @@ -903,31 +966,6 @@ public class SettingsActivity extends Activity return intentClass; } - /** - * 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. * @@ -941,64 +979,6 @@ public class SettingsActivity extends Activity setResult(resultCode, resultData); } - /** - * 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 @@ -1592,7 +1572,7 @@ public class SettingsActivity extends Activity * 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)} + * or {@link #switchToHeader(com.android.settings.SettingsActivity.Header, boolean, boolean)} * as appropriate. * * @param header The header that was selected. @@ -1600,7 +1580,7 @@ public class SettingsActivity extends Activity private void onHeaderClick(Header header) { if (header == null) return; if (header.fragment != null) { - switchToHeader(header, false); + switchToHeader(header, false, false); } else if (header.intent != null) { startActivity(header.intent); } diff --git a/src/com/android/settings/print/PrintServiceSettingsFragment.java b/src/com/android/settings/print/PrintServiceSettingsFragment.java index 357183fcc19..d5bfce20ebf 100644 --- a/src/com/android/settings/print/PrintServiceSettingsFragment.java +++ b/src/com/android/settings/print/PrintServiceSettingsFragment.java @@ -328,14 +328,6 @@ public class PrintServiceSettingsFragment extends SettingsPreferenceFragment final boolean enabled = arguments.getBoolean(PrintSettingsFragment.EXTRA_CHECKED); mToggleSwitch.setCheckedInternal(enabled); - // Title. - SettingsActivity activity = (SettingsActivity) getActivity(); - if (!activity.onIsHidingHeaders()) { - mOldActivityTitle = getActivity().getTitle(); - String title = arguments.getString(PrintSettingsFragment.EXTRA_TITLE); - getActivity().getActionBar().setTitle(title); - } - // Settings title and intent. String settingsTitle = arguments.getString(PrintSettingsFragment.EXTRA_SETTINGS_TITLE); String settingsComponentName = arguments.getString(