diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 3281adedf3f..ad783d3a523 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -567,7 +567,7 @@
+ android:value="com.android.settings.localepicker.LocaleListEditor" />
diff --git a/res/drawable/drag_handle.xml b/res/drawable/drag_handle.xml
new file mode 100644
index 00000000000..c01ee1cf1ba
--- /dev/null
+++ b/res/drawable/drag_handle.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
diff --git a/res/layout/locale_drag_cell.xml b/res/layout/locale_drag_cell.xml
new file mode 100644
index 00000000000..978e0adf9cc
--- /dev/null
+++ b/res/layout/locale_drag_cell.xml
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/layout/locale_order_list.xml b/res/layout/locale_order_list.xml
new file mode 100644
index 00000000000..97ba9a3a864
--- /dev/null
+++ b/res/layout/locale_order_list.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index db68d71f224..7a5d768002d 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -513,8 +513,27 @@
Next
-
- Language
+
+
+ Language preference
+
+
+ Remove
+
+
+ Add a language
+
+
+ Remove from your language preference?
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla egestas porta aliquet. Ut laoreet orci tellus, id cursus enim volutpat in.
+
+
+ Language removal error
+
+ Can’t remove all the languages, you should leave at least one.
+
Choose activity
diff --git a/res/xml/language_settings.xml b/res/xml/language_settings.xml
index fa96a56fbfa..83a0985bc90 100644
--- a/res/xml/language_settings.xml
+++ b/res/xml/language_settings.xml
@@ -4,9 +4,9 @@
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
-
+
http://www.apache.org/licenses/LICENSE-2.0
-
+
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -22,7 +22,7 @@
diff --git a/src/com/android/settings/InstrumentedFragment.java b/src/com/android/settings/InstrumentedFragment.java
index 58b8eb0b81d..bb2f948105f 100644
--- a/src/com/android/settings/InstrumentedFragment.java
+++ b/src/com/android/settings/InstrumentedFragment.java
@@ -37,6 +37,7 @@ public abstract class InstrumentedFragment extends PreferenceFragment {
public static final int DATA_USAGE_LIST = UNDECLARED + 7;
public static final int BILLING_CYCLE = UNDECLARED + 8;
public static final int APP_DATA_USAGE = UNDECLARED + 9;
+ public static final int USER_LOCALE_LIST = UNDECLARED + 10;
/**
* Declare the view of this category.
diff --git a/src/com/android/settings/LocalePicker.java b/src/com/android/settings/LocalePicker.java
deleted file mode 100644
index 950b79c38a6..00000000000
--- a/src/com/android/settings/LocalePicker.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings;
-
-import android.app.Dialog;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ListView;
-
-import com.android.settings.SettingsPreferenceFragment.SettingsDialogFragment;
-
-import java.util.Locale;
-
-public class LocalePicker extends com.android.internal.app.LocalePickerWithRegion
- implements com.android.internal.app.LocalePickerWithRegion.LocaleSelectionListener,
- DialogCreatable {
-
- private static final String TAG = "LocalePicker";
-
- private SettingsDialogFragment mDialogFragment;
- private static final int DLG_SHOW_GLOBAL_WARNING = 1;
- private static final String SAVE_TARGET_LOCALE = "locale";
-
- private Locale mTargetLocale;
-
- public LocalePicker() {
- super();
- setLocaleSelectionListener(this);
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- if (savedInstanceState != null && savedInstanceState.containsKey(SAVE_TARGET_LOCALE)) {
- mTargetLocale = new Locale(savedInstanceState.getString(SAVE_TARGET_LOCALE));
- }
- }
-
- @Override
- public View onCreateView(
- LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- final View view = super.onCreateView(inflater, container, savedInstanceState);
- final ListView list = (ListView) view.findViewById(android.R.id.list);
- Utils.forcePrepareCustomPreferencesList(container, view, list, false);
- return view;
- }
-
- @Override
- public void onLocaleSelected(final Locale locale) {
- if (Utils.hasMultipleUsers(getActivity())) {
- mTargetLocale = locale;
- showDialog(DLG_SHOW_GLOBAL_WARNING);
- } else {
- getActivity().onBackPressed();
- com.android.internal.app.LocalePicker.updateLocale(locale);
- }
- }
-
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
-
- if (mTargetLocale != null) {
- outState.putString(SAVE_TARGET_LOCALE, mTargetLocale.toString());
- }
- }
-
- protected void showDialog(int dialogId) {
- if (mDialogFragment != null) {
- Log.e(TAG, "Old dialog fragment not null!");
- }
- mDialogFragment = new SettingsDialogFragment(this, dialogId);
- mDialogFragment.show(getActivity().getFragmentManager(), Integer.toString(dialogId));
- }
-
- public Dialog onCreateDialog(final int dialogId) {
- return Utils.buildGlobalChangeWarningDialog(getActivity(),
- R.string.global_locale_change_title,
- new Runnable() {
- public void run() {
- removeDialog(dialogId);
- getActivity().onBackPressed();
- com.android.internal.app.LocalePicker.updateLocale(mTargetLocale);
- }
- }
- );
- }
-
- protected void removeDialog(int dialogId) {
- // mDialogFragment may not be visible yet in parent fragment's onResume().
- // To be able to dismiss dialog at that time, don't check
- // mDialogFragment.isVisible().
- if (mDialogFragment != null && mDialogFragment.getDialogId() == dialogId) {
- mDialogFragment.dismiss();
- }
- mDialogFragment = null;
- }
-}
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index dab2cb7607c..88cfc748d73 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -80,6 +80,7 @@ import com.android.settings.inputmethod.InputMethodAndLanguageSettings;
import com.android.settings.inputmethod.KeyboardLayoutPickerFragment;
import com.android.settings.inputmethod.SpellCheckersSettings;
import com.android.settings.inputmethod.UserDictionaryList;
+import com.android.settings.localepicker.LocaleListEditor;
import com.android.settings.location.LocationSettings;
import com.android.settings.nfc.AndroidBeam;
import com.android.settings.nfc.PaymentSettings;
@@ -246,7 +247,7 @@ public class SettingsActivity extends SettingsDrawerActivity
WifiP2pSettings.class.getName(),
VpnSettings.class.getName(),
DateTimeSettings.class.getName(),
- LocalePicker.class.getName(),
+ LocaleListEditor.class.getName(),
InputMethodAndLanguageSettings.class.getName(),
SpellCheckersSettings.class.getName(),
UserDictionaryList.class.getName(),
diff --git a/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java b/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java
index aa2d68a8cd7..9022538c094 100644
--- a/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java
+++ b/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java
@@ -43,6 +43,7 @@ import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceManager;
import android.support.v7.preference.PreferenceScreen;
import android.text.TextUtils;
+import android.util.LocaleList;
import android.view.InputDevice;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
@@ -50,6 +51,7 @@ import android.view.inputmethod.InputMethodSubtype;
import android.view.textservice.SpellCheckerInfo;
import android.view.textservice.TextServicesManager;
+import com.android.internal.app.LocaleHelper;
import com.android.internal.app.LocalePicker;
import com.android.internal.logging.MetricsLogger;
import com.android.settings.R;
@@ -266,8 +268,8 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
if (!mShowsOnlyFullImeAndKeyboardList) {
if (mLanguagePref != null) {
- String localeName = getLocaleName(getActivity());
- mLanguagePref.setSummary(localeName);
+ String localeNames = getLocaleNames(getActivity());
+ mLanguagePref.setSummary(localeNames);
}
updateUserDictionaryPreference(findPreference(KEY_USER_DICTIONARY_SETTINGS));
@@ -340,19 +342,9 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
return super.onPreferenceTreeClick(preference);
}
- private static String getLocaleName(Context context) {
- // We want to show the same string that the LocalePicker used.
- // TODO: should this method be in LocalePicker instead?
- Locale currentLocale = context.getResources().getConfiguration().locale;
- List locales = LocalePicker.getAllAssetLocales(context, true);
- for (LocalePicker.LocaleInfo locale : locales) {
- if (locale.getLocale().equals(currentLocale)) {
- return locale.getLabel();
- }
- }
- // This can't happen as long as the locale was one set by Settings.
- // Fall back in case a developer is testing an unsupported locale.
- return currentLocale.getDisplayName(currentLocale);
+ private static String getLocaleNames(Context context) {
+ final LocaleList locales = LocalePicker.getLocales();
+ return LocaleHelper.getDisplayLocaleList(locales, Locale.getDefault());
}
private void saveInputMethodSelectorVisibility(String value) {
@@ -665,8 +657,8 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
@Override
public void setListening(boolean listening) {
if (listening) {
- String localeName = getLocaleName(mContext);
- mSummaryLoader.setSummary(this, localeName);
+ String localeNames = getLocaleNames(mContext);
+ mSummaryLoader.setSummary(this, localeNames);
}
}
}
@@ -690,12 +682,12 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
// Locale picker.
if (context.getAssets().getLocales().length > 1) {
- String localeName = getLocaleName(context);
+ String localeNames = getLocaleNames(context);
SearchIndexableRaw indexable = new SearchIndexableRaw(context);
indexable.key = KEY_PHONE_LANGUAGE;
indexable.title = context.getString(R.string.phone_language);
- indexable.summaryOn = localeName;
- indexable.summaryOff = localeName;
+ indexable.summaryOn = localeNames;
+ indexable.summaryOff = localeNames;
indexable.screenTitle = screenTitle;
indexables.add(indexable);
}
diff --git a/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java b/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java
new file mode 100644
index 00000000000..b1f68b91e75
--- /dev/null
+++ b/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.localepicker;
+
+import android.content.Context;
+import android.support.v4.view.MotionEventCompat;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.helper.ItemTouchHelper;
+import android.util.LocaleList;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CompoundButton;
+
+import com.android.settings.R;
+
+import com.android.internal.app.LocalePicker;
+import com.android.internal.app.LocaleStore;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+
+
+class LocaleDragAndDropAdapter
+ extends RecyclerView.Adapter {
+
+ private final Context mContext;
+ private final List mFeedItemList;
+ private final ItemTouchHelper mItemTouchHelper;
+ private boolean mRemoveMode = false;
+ private boolean mDragEnabled = true;
+
+ class CustomViewHolder extends RecyclerView.ViewHolder implements View.OnTouchListener {
+ private final LocaleDragCell mLocaleDragCell;
+
+ public CustomViewHolder(LocaleDragCell view) {
+ super(view);
+ mLocaleDragCell = view;
+ mLocaleDragCell.getDragHandle().setOnTouchListener(this);
+ mLocaleDragCell.getTextLabel().setOnTouchListener(this);
+ mLocaleDragCell.getTranslateableLabel().setOnTouchListener(this);
+ }
+
+ public LocaleDragCell getLocaleDragCell() {
+ return mLocaleDragCell;
+ }
+
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ if (mDragEnabled) {
+ switch (MotionEventCompat.getActionMasked(event)) {
+ case MotionEvent.ACTION_DOWN:
+ mItemTouchHelper.startDrag(this);
+ }
+ }
+ return false;
+ }
+ }
+
+ public LocaleDragAndDropAdapter(Context context, List feedItemList) {
+ this.mFeedItemList = feedItemList;
+
+ this.mContext = context;
+ this.mItemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(
+ ItemTouchHelper.UP | ItemTouchHelper.DOWN, 0 /* no swipe */) {
+
+ @Override
+ public boolean onMove(RecyclerView view, RecyclerView.ViewHolder source,
+ RecyclerView.ViewHolder target) {
+ onItemMove(source.getAdapterPosition(), target.getAdapterPosition());
+ return true;
+ }
+
+ @Override
+ public void onSwiped(RecyclerView.ViewHolder viewHolder, int i) {
+ // Swipe is disabled, this is intentionally empty.
+ }
+ });
+ }
+
+ public void setRecyclerView(RecyclerView rv) {
+ mItemTouchHelper.attachToRecyclerView(rv);
+ }
+
+ @Override
+ public CustomViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
+ final LocaleDragCell item = (LocaleDragCell) LayoutInflater.from(mContext)
+ .inflate(R.layout.locale_drag_cell, viewGroup, false);
+ return new CustomViewHolder(item);
+ }
+
+ @Override
+ 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());
+ dragCell.setMiniLabel(Integer.toString(i + 1));
+ dragCell.setShowCheckbox(mRemoveMode);
+ dragCell.setShowMiniLabel(!mRemoveMode);
+ dragCell.setShowHandle(!mRemoveMode);
+ dragCell.setChecked(false);
+ dragCell.setTag(feedItem);
+ dragCell.getCheckbox()
+ .setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ LocaleStore.LocaleInfo feedItem =
+ (LocaleStore.LocaleInfo) holder.getLocaleDragCell().getTag();
+ feedItem.setChecked(isChecked);
+ }
+ });
+ }
+
+ @Override
+ public int getItemCount() {
+ int itemCount = (null != mFeedItemList ? mFeedItemList.size() : 0);
+ if (itemCount < 2 || mRemoveMode) {
+ setDragEnabled(false);
+ } else {
+ setDragEnabled(true);
+ }
+ return itemCount;
+ }
+
+ private void onItemMove(int fromPosition, int toPosition) {
+ Collections.swap(mFeedItemList, fromPosition, toPosition);
+ notifyItemChanged(fromPosition); // to update the numbers
+ notifyItemChanged(toPosition);
+ notifyItemMoved(fromPosition, toPosition);
+ }
+
+ void setRemoveMode(boolean removeMode) {
+ mRemoveMode = removeMode;
+ int itemCount = mFeedItemList.size();
+ for (int i = 0; i < itemCount; i++) {
+ mFeedItemList.get(i).setChecked(false);
+ notifyItemChanged(i);
+ }
+ }
+
+ void removeChecked() {
+ int itemCount = mFeedItemList.size();
+ for (int i = itemCount - 1; i >= 0; i--) {
+ if (mFeedItemList.get(i).getChecked()) {
+ mFeedItemList.remove(i);
+ }
+ }
+ notifyDataSetChanged();
+ doTheUpdate();
+ }
+
+ int getCheckedCount() {
+ int result = 0;
+ for (LocaleStore.LocaleInfo li : mFeedItemList) {
+ if (li.getChecked()) {
+ result++;
+ }
+ }
+ return result;
+ }
+
+ void addLocale(LocaleStore.LocaleInfo li) {
+ mFeedItemList.add(li);
+ notifyItemInserted(mFeedItemList.size() - 1);
+ doTheUpdate();
+ }
+
+ public void doTheUpdate() {
+ int count = mFeedItemList.size();
+ Locale[] newList = new Locale[count];
+
+ for (int i = 0; i < count; i++) {
+ LocaleStore.LocaleInfo li = mFeedItemList.get(i);
+ newList[i] = li.getLocale();
+ }
+
+ LocaleList ll = new LocaleList(newList);
+ LocalePicker.updateLocales(ll);
+ }
+
+ private void setDragEnabled(boolean enabled) {
+ mDragEnabled = enabled;
+ }
+}
diff --git a/src/com/android/settings/localepicker/LocaleDragCell.java b/src/com/android/settings/localepicker/LocaleDragCell.java
new file mode 100644
index 00000000000..8b1fa3c5f8f
--- /dev/null
+++ b/src/com/android/settings/localepicker/LocaleDragCell.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.localepicker;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.CheckBox;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.settings.R;
+
+class LocaleDragCell extends LinearLayout {
+ private TextView mLabel;
+ private TextView mMiniLabel;
+ private ImageView mLocalized;
+ private CheckBox mCheckbox;
+ private ImageView mDragHandle;
+
+ public LocaleDragCell(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mLabel = (TextView) findViewById(R.id.label);
+ mLocalized = (ImageView) findViewById(R.id.l10nWarn);
+ mMiniLabel = (TextView) findViewById(R.id.miniLabel);
+ mCheckbox = (CheckBox) findViewById(R.id.checkbox);
+ mDragHandle = (ImageView) findViewById(R.id.dragHandle);
+ }
+
+ public void setShowHandle(boolean showHandle) {
+ mDragHandle.setVisibility(showHandle ? VISIBLE : GONE);
+ invalidate();
+ requestLayout();
+ }
+
+ public void setShowCheckbox(boolean showCheckbox) {
+ mCheckbox.setVisibility(showCheckbox ? VISIBLE : GONE);
+ invalidate();
+ requestLayout();
+ }
+
+ public void setChecked(boolean checked) {
+ mCheckbox.setChecked(checked);
+ }
+
+ public void setShowMiniLabel(boolean showMiniLabel) {
+ mMiniLabel.setVisibility(showMiniLabel ? VISIBLE : GONE);
+ invalidate();
+ requestLayout();
+ }
+
+ public void setMiniLabel(String miniLabelText) {
+ mMiniLabel.setText(miniLabelText);
+ invalidate();
+ }
+
+ public void setLabel(String labelText) {
+ mLabel.setText(labelText);
+ invalidate();
+ }
+
+ public void setLocalized(boolean localized) {
+ mLocalized.setVisibility(localized ? INVISIBLE : VISIBLE);
+ invalidate();
+ }
+
+ public ImageView getDragHandle() {
+ return mDragHandle;
+ }
+
+ public ImageView getTranslateableLabel() {
+ return mLocalized;
+ }
+
+ public TextView getTextLabel() {
+ return mLabel;
+ }
+
+ public CheckBox getCheckbox() {
+ return mCheckbox;
+ }
+}
diff --git a/src/com/android/settings/localepicker/LocaleListEditor.java b/src/com/android/settings/localepicker/LocaleListEditor.java
new file mode 100644
index 00000000000..24e5e53d24a
--- /dev/null
+++ b/src/com/android/settings/localepicker/LocaleListEditor.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.localepicker;
+
+import android.app.AlertDialog;
+import android.app.FragmentTransaction;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.preference.PreferenceFragment;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.util.LocaleList;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+
+import com.android.settings.R;
+
+import com.android.internal.app.LocalePicker;
+import com.android.internal.app.LocalePickerWithRegion;
+import com.android.internal.app.LocaleStore;
+import com.android.settings.InstrumentedFragment;
+import com.android.settings.SettingsPreferenceFragment;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * Drag-and-drop editor for the user-ordered locale lists.
+ */
+public class LocaleListEditor extends SettingsPreferenceFragment
+ implements LocalePickerWithRegion.LocaleSelectedListener {
+
+ private static final int MENU_ID_REMOVE = Menu.FIRST + 1;
+
+ private LocaleDragAndDropAdapter mAdapter;
+ private Menu mMenu;
+ private boolean mRemoveMode;
+ private View mAddLanguage;
+
+ @Override
+ protected int getMetricsCategory() {
+ return InstrumentedFragment.USER_LOCALE_LIST;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setHasOptionsMenu(true);
+
+ LocaleStore.fillCache(this.getContext());
+ List feedsList = getUserLocaleList(this.getContext());
+ mAdapter = new LocaleDragAndDropAdapter(this.getContext(), feedsList);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstState) {
+ View result = super.onCreateView(inflater, container, savedInstState);
+ LinearLayout ll = (LinearLayout) result;
+ View myLayout = inflater.inflate(R.layout.locale_order_list, ll);
+
+ getActivity().setTitle(R.string.pref_title_lang_selection);
+
+ configureDragAndDrop(myLayout);
+ return result;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem menuItem) {
+ if (menuItem.getItemId() == MENU_ID_REMOVE) {
+ if (mRemoveMode) {
+ removeLocaleWarningDialog();
+ } else {
+ setRemoveMode(true);
+ }
+ return true;
+ }
+ return super.onOptionsItemSelected(menuItem);
+ }
+
+ 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);
+ }
+
+ private void removeLocaleWarningDialog() {
+ int checked = mAdapter.getCheckedCount();
+
+ // Nothing checked, just exit remove mode without a warning dialog
+ if (checked == 0) {
+ setRemoveMode(!mRemoveMode);
+ return;
+ }
+
+ // All locales selected, warning dialog, can't remove them all
+ if (checked == mAdapter.getItemCount()) {
+ new AlertDialog.Builder(getActivity())
+ .setTitle(R.string.dlg_remove_locales_error_title)
+ .setMessage(R.string.dlg_remove_locales_error_message)
+ .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ }
+ })
+ .create()
+ .show();
+ return;
+ }
+
+ new AlertDialog.Builder(getActivity())
+ .setTitle(R.string.dlg_remove_locales_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);
+ }
+ })
+ .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ mAdapter.removeChecked();
+ setRemoveMode(!mRemoveMode);
+ }
+ })
+ .create()
+ .show();
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ final MenuItem menuItem =
+ menu.add(Menu.NONE, MENU_ID_REMOVE, 0, R.string.locale_remove_menu);
+ menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_WITH_TEXT);
+ menuItem.setIcon(android.R.drawable.ic_menu_delete);
+ super.onCreateOptionsMenu(menu, inflater);
+ mMenu = menu;
+ }
+
+ private static List getUserLocaleList(Context context) {
+ List result = new ArrayList<>();
+
+ LocaleList localeList = LocalePicker.getLocales();
+ for (int i = 0; i < localeList.size(); i++) {
+ Locale locale = localeList.get(i);
+ result.add(LocaleStore.getLocaleInfo(locale));
+ }
+
+ return result;
+ }
+
+ private void configureDragAndDrop(View view) {
+ RecyclerView list = (RecyclerView) view.findViewById(R.id.dragList);
+ list.setLayoutManager(new LinearLayoutManager(this.getContext()));
+
+ list.setHasFixedSize(true);
+ mAdapter.setRecyclerView(list);
+ list.setAdapter(mAdapter);
+
+ mAddLanguage = view.findViewById(R.id.add_language);
+ mAddLanguage.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ final LocalePickerWithRegion selector = LocalePickerWithRegion.createLanguagePicker(
+ getContext(), LocaleListEditor.this, false /* translate only */);
+ getFragmentManager()
+ .beginTransaction()
+ .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
+ .replace(getId(), selector)
+ .addToBackStack("localeListEditor")
+ .commit();
+ }
+ });
+ }
+
+ @Override
+ public void onLocaleSelected(LocaleStore.LocaleInfo locale) {
+ mAdapter.addLocale(locale);
+ }
+
+}
diff --git a/src/com/android/settings/localepicker/LocaleRecyclerView.java b/src/com/android/settings/localepicker/LocaleRecyclerView.java
new file mode 100644
index 00000000000..b9c2b96b159
--- /dev/null
+++ b/src/com/android/settings/localepicker/LocaleRecyclerView.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.localepicker;
+
+import android.content.Context;
+import android.support.v7.widget.RecyclerView;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+
+class LocaleRecyclerView extends RecyclerView {
+ public LocaleRecyclerView(Context context) {
+ super(context);
+ }
+
+ public LocaleRecyclerView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public LocaleRecyclerView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent e) {
+ if (e.getAction() == MotionEvent.ACTION_UP) {
+ LocaleDragAndDropAdapter adapter = (LocaleDragAndDropAdapter) this.getAdapter();
+ if (adapter != null) {
+ adapter.doTheUpdate();
+ }
+ }
+ return super.onTouchEvent(e);
+ }
+}