Preserving list state on orientation change
Change-Id: Ibb75905573428e244b0cc4f0e61418e9f38101ed
diff --git a/src/com/android/contacts/activities/ContactListActivity.java b/src/com/android/contacts/activities/ContactListActivity.java
index 5e7abb4..c483d0b 100644
--- a/src/com/android/contacts/activities/ContactListActivity.java
+++ b/src/com/android/contacts/activities/ContactListActivity.java
@@ -39,6 +39,7 @@
import android.app.ActionBar;
import android.app.Activity;
import android.app.Dialog;
+import android.app.Fragment;
import android.app.FragmentTransaction;
import android.content.ContentValues;
import android.content.Intent;
@@ -65,6 +66,8 @@
private static final String TAG = "ContactListActivity";
+ private static final String KEY_MODE = "mode";
+
private static final int SUBACTIVITY_NEW_CONTACT = 1;
private static final int SUBACTIVITY_VIEW_CONTACT = 2;
private static final int SUBACTIVITY_DISPLAY_GROUP = 3;
@@ -102,9 +105,21 @@
}
@Override
+ public void onAttachFragment(Fragment fragment) {
+ if (fragment instanceof ContactBrowseListFragment) {
+ mListFragment = (ContactBrowseListFragment)fragment;
+ mListFragment.setOnContactListActionListener(new ContactBrowserActionListener());
+ }
+ }
+
+ @Override
protected void onCreate(Bundle savedState) {
super.onCreate(savedState);
+ if (savedState != null) {
+ mMode = savedState.getInt(KEY_MODE);
+ }
+
// Extract relevant information from the intent
mRequest = mIntentResolver.resolveIntent(getIntent());
if (!mRequest.isValid()) {
@@ -176,7 +191,9 @@
View navBarView = mNavigationBar.onCreateView(getLayoutInflater());
actionBar.setCustomNavigationMode(navBarView);
- configureListFragment();
+ if (mListFragment == null) {
+ configureListFragment();
+ }
setupContactDetailFragment();
@@ -202,9 +219,7 @@
return;
}
- if (mListFragment != null) {
- mListFragment.setOnContactListActionListener(null);
- }
+ closeListFragment();
mMode = mode;
switch (mMode) {
@@ -227,11 +242,28 @@
}
}
+ Bundle savedState = mNavigationBar.getSavedStateForMode(mMode);
+ if (savedState != null) {
+ mListFragment.restoreSavedState(savedState);
+ }
+
openFragmentTransaction()
.replace(R.id.two_pane_list, mListFragment)
.commit();
}
+ private void closeListFragment() {
+ if (mListFragment != null) {
+ mListFragment.setOnContactListActionListener(null);
+
+ if (mNavigationBar != null) {
+ Bundle state = new Bundle();
+ mListFragment.onSaveInstanceState(state);
+ mNavigationBar.saveStateForMode(mMode, state);
+ }
+ }
+ }
+
private void setupContactDetailFragment() {
// No editor here
closeEditorFragment();
@@ -736,6 +768,7 @@
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
+ outState.putInt(KEY_MODE, mMode);
if (mNavigationBar != null) {
mNavigationBar.onSaveInstanceState(outState);
}
diff --git a/src/com/android/contacts/activities/NavigationBar.java b/src/com/android/contacts/activities/NavigationBar.java
index 58b2d35..5b6caa6 100644
--- a/src/com/android/contacts/activities/NavigationBar.java
+++ b/src/com/android/contacts/activities/NavigationBar.java
@@ -30,6 +30,8 @@
import android.widget.ImageView;
import android.widget.ToggleButton;
+import java.util.HashMap;
+
/**
* Navigation bar at the top of the Contacts activity.
*/
@@ -43,6 +45,10 @@
private static final String EXTRA_KEY_MODE = "navBar.mode";
private static final String EXTRA_KEY_QUERY = "navBar.query";
+ private static final String KEY_MODE_CONTACTS = "mode_contacts";
+ private static final String KEY_MODE_FAVORITES = "mode_favorites";
+ private static final String KEY_MODE_SEARCH = "mode_search";
+
public static final int MODE_CONTACTS = 0;
public static final int MODE_FAVORITES = 1;
public static final int MODE_SEARCH = 2;
@@ -50,6 +56,9 @@
private int mMode = MODE_CONTACTS;
private int mDefaultMode = MODE_CONTACTS;
private String mQueryString;
+ private HashMap<Integer, Bundle> mSavedStateByMode = new HashMap<Integer, Bundle>();
+
+
private SearchEditText mSearchEditText;
private View mNavigationBar;
@@ -74,6 +83,9 @@
mDefaultMode = savedState.getInt(EXTRA_KEY_DEFAULT_MODE, -1);
mMode = savedState.getInt(EXTRA_KEY_MODE, -1);
mQueryString = savedState.getString(EXTRA_KEY_QUERY);
+ restoreSavedState(savedState, MODE_CONTACTS, KEY_MODE_CONTACTS);
+ restoreSavedState(savedState, MODE_FAVORITES, KEY_MODE_FAVORITES);
+ restoreSavedState(savedState, MODE_SEARCH, KEY_MODE_SEARCH);
}
int actionCode = request.getActionCode();
@@ -206,9 +218,36 @@
setMode(mDefaultMode);
}
+ public void saveStateForMode(int mode, Bundle state) {
+ mSavedStateByMode.put(mode, state);
+ }
+
+ public Bundle getSavedStateForMode(int mode) {
+ return mSavedStateByMode.get(mode);
+ }
+
public void onSaveInstanceState(Bundle outState) {
outState.putInt(EXTRA_KEY_DEFAULT_MODE, mDefaultMode);
outState.putInt(EXTRA_KEY_MODE, mMode);
outState.putString(EXTRA_KEY_QUERY, mQueryString);
+ saveInstanceState(outState, MODE_CONTACTS, KEY_MODE_CONTACTS);
+ saveInstanceState(outState, MODE_FAVORITES, KEY_MODE_FAVORITES);
+ saveInstanceState(outState, MODE_SEARCH, KEY_MODE_SEARCH);
+ }
+
+ private void saveInstanceState(Bundle outState, int mode, String key) {
+ Bundle state = mSavedStateByMode.get(mode);
+ if (state != null) {
+ outState.putParcelable(key, state);
+ }
+ }
+
+ private void restoreSavedState(Bundle savedState, int mode, String key) {
+ Bundle bundle = savedState.getParcelable(key);
+ if (bundle == null) {
+ mSavedStateByMode.remove(mode);
+ } else {
+ mSavedStateByMode.put(mode, bundle);
+ }
}
}
diff --git a/src/com/android/contacts/list/ContactEntryListFragment.java b/src/com/android/contacts/list/ContactEntryListFragment.java
index 0602097..2eedf0c 100644
--- a/src/com/android/contacts/list/ContactEntryListFragment.java
+++ b/src/com/android/contacts/list/ContactEntryListFragment.java
@@ -22,9 +22,9 @@
import com.android.contacts.ContactsSearchManager;
import com.android.contacts.R;
import com.android.contacts.ui.ContactsPreferences;
+import com.android.contacts.widget.CompositeCursorAdapter.Partition;
import com.android.contacts.widget.ContextMenuAdapter;
import com.android.contacts.widget.InstrumentedLoaderManagingFragment;
-import com.android.contacts.widget.CompositeCursorAdapter.Partition;
import android.accounts.Account;
import android.accounts.AccountManager;
@@ -43,28 +43,27 @@
import android.os.Parcelable;
import android.os.RemoteException;
import android.provider.ContactsContract;
-import android.provider.Settings;
import android.provider.ContactsContract.Directory;
import android.provider.ContactsContract.ProviderStatus;
+import android.provider.Settings;
import android.telephony.TelephonyManager;
-import android.text.Html;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.View.OnTouchListener;
+import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.AbsListView;
+import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
-import android.widget.AbsListView.OnScrollListener;
-import android.widget.AdapterView.OnItemClickListener;
/**
* Common base class for various contact-related list fragments.
@@ -77,7 +76,16 @@
private static final String TAG = "ContactEntryListFragment";
- private static final String LIST_STATE_KEY = "liststate";
+ private static final String KEY_LIST_STATE = "liststate";
+ private static final String KEY_SECTION_HEADER_DISPLAY_ENABLED = "sectionHeaderDisplayEnabled";
+ private static final String KEY_PHOTO_LOADER_ENABLED = "photoLoaderEnabled";
+ private static final String KEY_SEARCH_MODE = "searchMode";
+ private static final String KEY_AIZY_ENABLED = "aizyEnabled";
+ private static final String KEY_QUERY_STRING = "queryString";
+ private static final String KEY_DIRECTORY_SEARCH_ENABLED = "directorySearchEnabled";
+ private static final String KEY_SELECTION_VISIBLE = "selectionVisible";
+ private static final String KEY_REQUEST = "request";
+ private static final String KEY_LEGACY_COMPATIBILITY = "legacyCompatibility";
private static final String DIRECTORY_ID_ARG_KEY = "directoryId";
@@ -90,6 +98,8 @@
private String mQueryString;
private boolean mDirectorySearchEnabled;
private boolean mSelectionVisible;
+ private ContactsRequest mRequest;
+ private boolean mLegacyCompatibility;
private T mAdapter;
private View mView;
@@ -101,7 +111,6 @@
*/
private Parcelable mListState;
- private boolean mLegacyCompatibility;
private int mDisplayOrder;
private int mSortOrder;
@@ -122,8 +131,6 @@
*/
private boolean mLoadPriorityDirectoriesOnly;
- private ContactsRequest mRequest;
-
private Context mContext;
protected abstract View inflateView(LayoutInflater inflater, ViewGroup container);
@@ -175,6 +182,49 @@
protected void onInitializeLoaders() {
}
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putBoolean(KEY_SECTION_HEADER_DISPLAY_ENABLED, mSectionHeaderDisplayEnabled);
+ outState.putBoolean(KEY_PHOTO_LOADER_ENABLED, mPhotoLoaderEnabled);
+ outState.putBoolean(KEY_SEARCH_MODE, mSearchMode);
+ outState.putBoolean(KEY_AIZY_ENABLED, mAizyEnabled);
+ outState.putBoolean(KEY_DIRECTORY_SEARCH_ENABLED, mDirectorySearchEnabled);
+ outState.putBoolean(KEY_SELECTION_VISIBLE, mSelectionVisible);
+ outState.putBoolean(KEY_LEGACY_COMPATIBILITY, mLegacyCompatibility);
+ outState.putString(KEY_QUERY_STRING, mQueryString);
+ outState.putParcelable(KEY_REQUEST, mRequest);
+
+ if (mListView != null) {
+ outState.putParcelable(KEY_LIST_STATE, mListView.onSaveInstanceState());
+ }
+ }
+
+ @Override
+ public void onCreate(Bundle savedState) {
+ super.onCreate(savedState);
+ restoreSavedState(savedState);
+ }
+
+ public void restoreSavedState(Bundle savedState) {
+ if (savedState == null) {
+ return;
+ }
+
+ mSectionHeaderDisplayEnabled = savedState.getBoolean(KEY_SECTION_HEADER_DISPLAY_ENABLED);
+ mPhotoLoaderEnabled = savedState.getBoolean(KEY_PHOTO_LOADER_ENABLED);
+ mSearchMode = savedState.getBoolean(KEY_SEARCH_MODE);
+ mAizyEnabled = savedState.getBoolean(KEY_AIZY_ENABLED);
+ mDirectorySearchEnabled = savedState.getBoolean(KEY_DIRECTORY_SEARCH_ENABLED);
+ mSelectionVisible = savedState.getBoolean(KEY_SELECTION_VISIBLE);
+ mLegacyCompatibility = savedState.getBoolean(KEY_LEGACY_COMPATIBILITY);
+ mQueryString = savedState.getString(KEY_QUERY_STRING);
+ mRequest = savedState.getParcelable(KEY_REQUEST);
+
+ // Retrieve list state. This will be applied in onLoadFinished
+ mListState = savedState.getParcelable(KEY_LIST_STATE);
+ }
+
/**
* Returns the parsed intent that started the activity hosting this fragment.
*/
@@ -457,11 +507,11 @@
mLegacyCompatibility = flag;
}
- public int getContactNameDisplayOrder() {
+ protected int getContactNameDisplayOrder() {
return mDisplayOrder;
}
- public void setContactNameDisplayOrder(int displayOrder) {
+ protected void setContactNameDisplayOrder(int displayOrder) {
mDisplayOrder = displayOrder;
if (mAdapter != null) {
mAdapter.setContactNameDisplayOrder(displayOrder);
@@ -496,15 +546,6 @@
}
@Override
- public void onCreate(Bundle savedState) {
- super.onCreate(savedState);
- // Retrieve list state. This will be applied in onLoadFinished
- if (savedState != null) {
- mListState = savedState.getParcelable(LIST_STATE_KEY);
- }
- }
-
- @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
onCreateView(inflater, container);
@@ -689,15 +730,6 @@
finish();
}
- @Override
- public void onSaveInstanceState(Bundle icicle) {
- super.onSaveInstanceState(icicle);
- if (mListView != null) {
- mListState = mListView.onSaveInstanceState();
- icicle.putParcelable(LIST_STATE_KEY, mListState);
- }
- }
-
/**
* Restore the list state after the adapter is populated.
*/
diff --git a/src/com/android/contacts/list/DefaultContactBrowseListFragment.java b/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
index a89de48..2133d49 100644
--- a/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
+++ b/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
@@ -20,6 +20,7 @@
import android.content.SharedPreferences;
import android.database.Cursor;
+import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.LayoutInflater;
import android.view.View;
@@ -33,6 +34,11 @@
*/
public class DefaultContactBrowseListFragment extends ContactBrowseListFragment {
+ private static final String KEY_EDIT_MODE = "editMode";
+ private static final String KEY_CREATE_CONTACT_ENABLED = "createContactEnabled";
+ private static final String KEY_DISPLAY_WITH_PHONES_ONLY = "displayWithPhonesOnly";
+ private static final String KEY_VISIBLE_CONTACTS_RESTRICTION = "visibleContactsRestriction";
+
private boolean mEditMode;
private boolean mCreateContactEnabled;
private int mDisplayWithPhonesOnlyOption = ContactsRequest.DISPLAY_ONLY_WITH_PHONES_DISABLED;
@@ -46,6 +52,30 @@
}
@Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putBoolean(KEY_EDIT_MODE, mEditMode);
+ outState.putBoolean(KEY_CREATE_CONTACT_ENABLED, mCreateContactEnabled);
+ outState.putInt(KEY_DISPLAY_WITH_PHONES_ONLY, mDisplayWithPhonesOnlyOption);
+ outState.putBoolean(KEY_VISIBLE_CONTACTS_RESTRICTION, mVisibleContactsRestrictionEnabled);
+ }
+
+ @Override
+ public void restoreSavedState(Bundle savedState) {
+ super.restoreSavedState(savedState);
+
+ if (savedState == null) {
+ return;
+ }
+
+ mEditMode = savedState.getBoolean(KEY_EDIT_MODE);
+ mCreateContactEnabled = savedState.getBoolean(KEY_CREATE_CONTACT_ENABLED);
+ mDisplayWithPhonesOnlyOption = savedState.getInt(KEY_DISPLAY_WITH_PHONES_ONLY);
+ mVisibleContactsRestrictionEnabled =
+ savedState.getBoolean(KEY_VISIBLE_CONTACTS_RESTRICTION);
+ }
+
+ @Override
protected void prepareEmptyView() {
if (isShowingContactsWithPhonesOnly()) {
setEmptyText(R.string.noContactsWithPhoneNumbers);