Merge "Fix checkboxes and warning dialog lost when device rotates" into nyc-dev
diff --git a/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java b/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java
index a78c60d..2ce4e72 100644
--- a/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java
+++ b/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.graphics.Canvas;
+import android.os.Bundle;
import android.support.v4.view.MotionEventCompat;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
@@ -36,6 +37,7 @@
import com.android.settings.R;
import java.text.NumberFormat;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
@@ -45,6 +47,7 @@
extends RecyclerView.Adapter<LocaleDragAndDropAdapter.CustomViewHolder> {
private static final String TAG = "LocaleDragAndDropAdapter";
+ private static final String CFGKEY_SELECTED_LOCALES = "selectedLocales";
private final Context mContext;
private final List<LocaleStore.LocaleInfo> mFeedItemList;
private final ItemTouchHelper mItemTouchHelper;
@@ -105,6 +108,7 @@
private static final int SELECTION_LOST = 0;
private static final int SELECTION_UNCHANGED = -1;
private int mSelectionStatus = SELECTION_UNCHANGED;
+
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView,
RecyclerView.ViewHolder viewHolder, float dX, float dY,
@@ -148,7 +152,6 @@
public void onBindViewHolder(final CustomViewHolder holder, int i) {
final LocaleStore.LocaleInfo feedItem = mFeedItemList.get(i);
final LocaleDragCell dragCell = holder.getLocaleDragCell();
-
String label = feedItem.getFullNameNative();
dragCell.setLabel(label);
dragCell.setLocalized(feedItem.isTranslated());
@@ -156,7 +159,7 @@
dragCell.setShowCheckbox(mRemoveMode);
dragCell.setShowMiniLabel(!mRemoveMode);
dragCell.setShowHandle(!mRemoveMode && mDragEnabled);
- dragCell.setChecked(false);
+ dragCell.setChecked(mRemoveMode ? feedItem.getChecked() : false);
dragCell.setTag(feedItem);
dragCell.getCheckbox()
.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@@ -286,4 +289,40 @@
private void setDragEnabled(boolean enabled) {
mDragEnabled = enabled;
}
+
+ /**
+ * Saves the list of checked locales to preserve status when the list is destroyed.
+ * (for instance when the device is rotated)
+ * @param outInstanceState Bundle in which to place the saved state
+ */
+ public void saveState(Bundle outInstanceState) {
+ if (outInstanceState != null) {
+ final ArrayList<String> selectedLocales = new ArrayList<>();
+ for (LocaleStore.LocaleInfo li : mFeedItemList) {
+ if (li.getChecked()) {
+ selectedLocales.add(li.getId());
+ }
+ }
+ outInstanceState.putStringArrayList(CFGKEY_SELECTED_LOCALES, selectedLocales);
+ }
+ }
+
+ /**
+ * Restores the list of checked locales to preserve status when the list is recreated.
+ * (for instance when the device is rotated)
+ * @param savedInstanceState Bundle with the data saved by {@link #saveState(Bundle)}
+ */
+ public void restoreState(Bundle savedInstanceState) {
+ if (savedInstanceState != null && mRemoveMode) {
+ final ArrayList<String> selectedLocales =
+ savedInstanceState.getStringArrayList(CFGKEY_SELECTED_LOCALES);
+ if (selectedLocales == null || selectedLocales.isEmpty()) {
+ return;
+ }
+ for (LocaleStore.LocaleInfo li : mFeedItemList) {
+ li.setChecked(selectedLocales.contains(li.getId()));
+ }
+ notifyItemRangeChanged(0, mFeedItemList.size());
+ }
+ }
}
diff --git a/src/com/android/settings/localepicker/LocaleListEditor.java b/src/com/android/settings/localepicker/LocaleListEditor.java
index 63649d7..3287d39 100644
--- a/src/com/android/settings/localepicker/LocaleListEditor.java
+++ b/src/com/android/settings/localepicker/LocaleListEditor.java
@@ -31,6 +31,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
+
import com.android.internal.app.LocalePicker;
import com.android.internal.app.LocalePickerWithRegion;
import com.android.internal.app.LocaleStore;
@@ -48,12 +49,15 @@
public class LocaleListEditor extends SettingsPreferenceFragment
implements LocalePickerWithRegion.LocaleSelectedListener {
+ private static final String CFGKEY_REMOVE_MODE = "localeRemoveMode";
+ private static final String CFGKEY_REMOVE_DIALOG = "showingLocaleRemoveDialog";
private static final int MENU_ID_REMOVE = Menu.FIRST + 1;
private LocaleDragAndDropAdapter mAdapter;
private Menu mMenu;
- private boolean mRemoveMode;
private View mAddLanguage;
+ private boolean mRemoveMode;
+ private boolean mShowingRemoveDialog;
@Override
protected int getMetricsCategory() {
@@ -83,14 +87,44 @@
}
@Override
+ public void onViewStateRestored(Bundle savedInstanceState) {
+ super.onViewStateRestored(savedInstanceState);
+ if (savedInstanceState != null) {
+ mRemoveMode = savedInstanceState.getBoolean(CFGKEY_REMOVE_MODE, false);
+ mShowingRemoveDialog = savedInstanceState.getBoolean(CFGKEY_REMOVE_DIALOG, false);
+ }
+ setRemoveMode(mRemoveMode);
+ mAdapter.restoreState(savedInstanceState);
+
+ if (mShowingRemoveDialog) {
+ showRemoveLocaleWarningDialog();
+ }
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putBoolean(CFGKEY_REMOVE_MODE, mRemoveMode);
+ outState.putBoolean(CFGKEY_REMOVE_DIALOG, mShowingRemoveDialog);
+ mAdapter.saveState(outState);
+ }
+
+ @Override
public boolean onOptionsItemSelected(MenuItem menuItem) {
- if (menuItem.getItemId() == MENU_ID_REMOVE) {
- if (mRemoveMode) {
- removeLocaleWarningDialog();
- } else {
- setRemoveMode(true);
- }
- return true;
+ switch (menuItem.getItemId()) {
+ case MENU_ID_REMOVE:
+ if (mRemoveMode) {
+ showRemoveLocaleWarningDialog();
+ } else {
+ setRemoveMode(true);
+ }
+ return true;
+ case android.R.id.home:
+ if (mRemoveMode) {
+ setRemoveMode(false);
+ return true;
+ }
+ break;
}
return super.onOptionsItemSelected(menuItem);
}
@@ -98,12 +132,15 @@
private void setRemoveMode(boolean mRemoveMode) {
this.mRemoveMode = mRemoveMode;
mAdapter.setRemoveMode(mRemoveMode);
- mMenu.findItem(MENU_ID_REMOVE).setShowAsAction(
- mRemoveMode ? MenuItem.SHOW_AS_ACTION_ALWAYS : MenuItem.SHOW_AS_ACTION_NEVER);
mAddLanguage.setVisibility(mRemoveMode ? View.INVISIBLE : View.VISIBLE);
+ updateVisibilityOfRemoveMenu();
}
- private void removeLocaleWarningDialog() {
+ // Show the appropriate warning when the user tries to remove locales.
+ // Shows no warning if there is no locale checked, shows a warning
+ // about removing all the locales if all of them are checked, and
+ // a "regular" warning otherwise.
+ private void showRemoveLocaleWarningDialog() {
int checkedCount = mAdapter.getCheckedCount();
// Nothing checked, just exit remove mode without a warning dialog
@@ -114,6 +151,7 @@
// All locales selected, warning dialog, can't remove them all
if (checkedCount == mAdapter.getItemCount()) {
+ mShowingRemoveDialog = true;
new AlertDialog.Builder(getActivity())
.setTitle(R.string.dlg_remove_locales_error_title)
.setMessage(R.string.dlg_remove_locales_error_message)
@@ -122,6 +160,12 @@
public void onClick(DialogInterface dialog, int which) {
}
})
+ .setOnDismissListener(new DialogInterface.OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ mShowingRemoveDialog = false;
+ }
+ })
.create()
.show();
return;
@@ -129,21 +173,38 @@
final String title = getResources().getQuantityString(R.plurals.dlg_remove_locales_title,
checkedCount);
+ mShowingRemoveDialog = true;
new AlertDialog.Builder(getActivity())
.setTitle(title)
.setMessage(R.string.dlg_remove_locales_message)
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
- setRemoveMode(!mRemoveMode);
+ setRemoveMode(false);
}
})
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
+ // This is a sensitive area to change.
+ // removeChecked() triggers a system update and "kills" the frame.
+ // This means that saveState + restoreState are called before
+ // setRemoveMode is called.
+ // So we want that mRemoveMode and dialog status have the right values
+ // before that save.
+ // We can't just call setRemoveMode(false) before calling removeCheched
+ // because that unchecks all items and removeChecked would have nothing
+ // to remove.
+ mRemoveMode = false;
+ mShowingRemoveDialog = false;
mAdapter.removeChecked();
- setRemoveMode(!mRemoveMode);
- updateVisibilityOfRemoveMenu();
+ setRemoveMode(false);
+ }
+ })
+ .setOnDismissListener(new DialogInterface.OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ mShowingRemoveDialog = false;
}
})
.create()
@@ -208,8 +269,14 @@
// Hide the "Remove" menu if there is only one locale in the list, show it otherwise
// This is called when the menu is first created, and then one add / remove locale
private void updateVisibilityOfRemoveMenu() {
+ if (mMenu == null) {
+ return;
+ }
+
final MenuItem menuItemRemove = mMenu.findItem(MENU_ID_REMOVE);
if (menuItemRemove != null) {
+ menuItemRemove.setShowAsAction(
+ mRemoveMode ? MenuItem.SHOW_AS_ACTION_ALWAYS : MenuItem.SHOW_AS_ACTION_NEVER);
menuItemRemove.setVisible(mAdapter.getItemCount() > 1);
}
}