11808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita/* 21808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita * Copyright (C) 2016 The Android Open Source Project 31808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita * 41808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita * Licensed under the Apache License, Version 2.0 (the "License"); 51808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita * you may not use this file except in compliance with the License. 61808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita * You may obtain a copy of the License at 71808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita * 81808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita * http://www.apache.org/licenses/LICENSE-2.0 91808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita * 101808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita * Unless required by applicable law or agreed to in writing, software 111808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita * distributed under the License is distributed on an "AS IS" BASIS, 121808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita * See the License for the specific language governing permissions and 141808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita * limitations under the License. 151808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita */ 161808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 171808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nitapackage com.android.internal.app; 181808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 193f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournaderimport android.annotation.NonNull; 203f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournaderimport android.annotation.Nullable; 213f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournaderimport android.content.Context; 223f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournaderimport android.content.res.Configuration; 2324215ecadce5f44de33959b4f512482f39ac4c92Mihai Nitaimport android.text.TextUtils; 241808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nitaimport android.view.LayoutInflater; 251808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nitaimport android.view.View; 261808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nitaimport android.view.ViewGroup; 271808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nitaimport android.widget.BaseAdapter; 281808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nitaimport android.widget.Filter; 291808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nitaimport android.widget.Filterable; 301808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nitaimport android.widget.TextView; 311808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 321808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nitaimport com.android.internal.R; 331808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 341808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nitaimport java.util.ArrayList; 351808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nitaimport java.util.Collections; 361808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nitaimport java.util.Locale; 371808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nitaimport java.util.Set; 381808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 391808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 401808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita/** 411808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita * This adapter wraps around a regular ListAdapter for LocaleInfo, and creates 2 sections. 421808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita * 431808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita * <p>The first section contains "suggested" languages (usually including a region), 441808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita * the second section contains all the languages within the original adapter. 451808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita * The "others" might still include languages that appear in the "suggested" section.</p> 461808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita * 471808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita * <p>Example: if we show "German Switzerland" as "suggested" (based on SIM, let's say), 481808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita * then "German" will still show in the "others" section, clicking on it will only show the 491808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita * countries for all the other German locales, but not Switzerland 501808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita * (Austria, Belgium, Germany, Liechtenstein, Luxembourg)</p> 511808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita */ 52137b96e3a41edc19a53f7218ef3e53adbfcfd340Mihai Nitapublic class SuggestedLocaleAdapter extends BaseAdapter implements Filterable { 531808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita private static final int TYPE_HEADER_SUGGESTED = 0; 541808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita private static final int TYPE_HEADER_ALL_OTHERS = 1; 551808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita private static final int TYPE_LOCALE = 2; 5686235d497007ad17ddec7e659fb0e0c36b010745Mihai Nita private static final int MIN_REGIONS_FOR_SUGGESTIONS = 6; 571808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 581808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita private ArrayList<LocaleStore.LocaleInfo> mLocaleOptions; 591808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita private ArrayList<LocaleStore.LocaleInfo> mOriginalLocaleOptions; 601808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita private int mSuggestionCount; 611808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita private final boolean mCountryMode; 621808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita private LayoutInflater mInflater; 631808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 643f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader private Locale mDisplayLocale = null; 653f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader // used to potentially cache a modified Context that uses mDisplayLocale 663f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader private Context mContextOverride = null; 673f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader 68137b96e3a41edc19a53f7218ef3e53adbfcfd340Mihai Nita public SuggestedLocaleAdapter(Set<LocaleStore.LocaleInfo> localeOptions, boolean countryMode) { 691808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita mCountryMode = countryMode; 701808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita mLocaleOptions = new ArrayList<>(localeOptions.size()); 711808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita for (LocaleStore.LocaleInfo li : localeOptions) { 721808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita if (li.isSuggested()) { 731808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita mSuggestionCount++; 741808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 751808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita mLocaleOptions.add(li); 761808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 771808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 781808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 791808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita @Override 801808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita public boolean areAllItemsEnabled() { 811808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita return false; 821808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 831808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 841808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita @Override 851808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita public boolean isEnabled(int position) { 861808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita return getItemViewType(position) == TYPE_LOCALE; 871808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 881808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 891808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita @Override 901808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita public int getItemViewType(int position) { 911808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita if (!showHeaders()) { 921808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita return TYPE_LOCALE; 931808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } else { 941808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita if (position == 0) { 951808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita return TYPE_HEADER_SUGGESTED; 961808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 971808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita if (position == mSuggestionCount + 1) { 981808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita return TYPE_HEADER_ALL_OTHERS; 991808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 1001808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita return TYPE_LOCALE; 1011808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 1021808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 1031808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 1041808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita @Override 1051808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita public int getViewTypeCount() { 1061808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita if (showHeaders()) { 1071808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita return 3; // Two headers in addition to the locales 1081808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } else { 1091808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita return 1; // Locales items only 1101808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 1111808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 1121808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 1131808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita @Override 1141808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita public int getCount() { 1151808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita if (showHeaders()) { 1161808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita return mLocaleOptions.size() + 2; // 2 extra for the headers 1171808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } else { 1181808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita return mLocaleOptions.size(); 1191808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 1201808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 1211808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 1221808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita @Override 1231808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita public Object getItem(int position) { 1241808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita int offset = 0; 1251808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita if (showHeaders()) { 1261808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita offset = position > mSuggestionCount ? -2 : -1; 1271808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 1281808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 1291808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita return mLocaleOptions.get(position + offset); 1301808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 1311808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 1321808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita @Override 1331808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita public long getItemId(int position) { 1341808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita return position; 1351808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 1361808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 1373f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader /** 1383f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader * Overrides the locale used to display localized labels. Setting the locale to null will reset 1393f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader * the Adapter to use the default locale for the labels. 1403f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader */ 1413f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader public void setDisplayLocale(@NonNull Context context, @Nullable Locale locale) { 1423f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader if (locale == null) { 1433f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader mDisplayLocale = null; 1443f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader mContextOverride = null; 1453f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader } else if (!locale.equals(mDisplayLocale)) { 1463f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader mDisplayLocale = locale; 1473f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader final Configuration configOverride = new Configuration(); 1483f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader configOverride.setLocale(locale); 1493f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader mContextOverride = context.createConfigurationContext(configOverride); 1503f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader } 1513f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader } 1523f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader 1533f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader private void setTextTo(@NonNull TextView textView, int resId) { 1543f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader if (mContextOverride == null) { 1553f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader textView.setText(resId); 1563f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader } else { 1573f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader textView.setText(mContextOverride.getText(resId)); 1583f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader // If mContextOverride is not null, mDisplayLocale can't be null either. 1593f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader } 1603f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader } 1613f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader 1621808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita @Override 1631808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita public View getView(int position, View convertView, ViewGroup parent) { 1641808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita if (convertView == null && mInflater == null) { 1651808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita mInflater = LayoutInflater.from(parent.getContext()); 1661808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 1671808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 1681808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita int itemType = getItemViewType(position); 1691808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita switch (itemType) { 1701808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita case TYPE_HEADER_SUGGESTED: // intentional fallthrough 1711808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita case TYPE_HEADER_ALL_OTHERS: 1721808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita // Covers both null, and "reusing" a wrong kind of view 1731808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita if (!(convertView instanceof TextView)) { 1741808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita convertView = mInflater.inflate(R.layout.language_picker_section_header, 1751808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita parent, false); 1761808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 1771808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita TextView textView = (TextView) convertView; 1781808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita if (itemType == TYPE_HEADER_SUGGESTED) { 1793f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader setTextTo(textView, R.string.language_picker_section_suggested); 1801808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } else { 181543e45babeb200a3586bbbd8ffd0b6e2f3f0687cMihai Nita if (mCountryMode) { 1823f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader setTextTo(textView, R.string.region_picker_section_all); 183543e45babeb200a3586bbbd8ffd0b6e2f3f0687cMihai Nita } else { 1843f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader setTextTo(textView, R.string.language_picker_section_all); 185543e45babeb200a3586bbbd8ffd0b6e2f3f0687cMihai Nita } 1861808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 1873f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader textView.setTextLocale( 1883f01530a684755dbebeb15bbdb70d0b0cd11dbd0Roozbeh Pournader mDisplayLocale != null ? mDisplayLocale : Locale.getDefault()); 1891808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita break; 1901808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita default: 1911808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita // Covers both null, and "reusing" a wrong kind of view 1921808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita if (!(convertView instanceof ViewGroup)) { 1931808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita convertView = mInflater.inflate(R.layout.language_picker_item, parent, false); 1941808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 1951808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 1961808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita TextView text = (TextView) convertView.findViewById(R.id.locale); 1971808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita LocaleStore.LocaleInfo item = (LocaleStore.LocaleInfo) getItem(position); 198f1f39cf1936df2d28133e43390f72f3dbb40ffc8Mihai Nita text.setText(item.getLabel(mCountryMode)); 199502141d50bbd188a37b59f2ea9fa794a296f7247Mihai Nita text.setTextLocale(item.getLocale()); 20043af6366f2aad8c0c0a8ae1367215961ccd75c29Mihai Nita text.setContentDescription(item.getContentDescription(mCountryMode)); 20124215ecadce5f44de33959b4f512482f39ac4c92Mihai Nita if (mCountryMode) { 20224215ecadce5f44de33959b4f512482f39ac4c92Mihai Nita int layoutDir = TextUtils.getLayoutDirectionFromLocale(item.getParent()); 20324215ecadce5f44de33959b4f512482f39ac4c92Mihai Nita //noinspection ResourceType 20424215ecadce5f44de33959b4f512482f39ac4c92Mihai Nita convertView.setLayoutDirection(layoutDir); 20524215ecadce5f44de33959b4f512482f39ac4c92Mihai Nita text.setTextDirection(layoutDir == View.LAYOUT_DIRECTION_RTL 20624215ecadce5f44de33959b4f512482f39ac4c92Mihai Nita ? View.TEXT_DIRECTION_RTL 20724215ecadce5f44de33959b4f512482f39ac4c92Mihai Nita : View.TEXT_DIRECTION_LTR); 20824215ecadce5f44de33959b4f512482f39ac4c92Mihai Nita } 2091808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 2101808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita return convertView; 2111808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 2121808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 2131808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita private boolean showHeaders() { 21486235d497007ad17ddec7e659fb0e0c36b010745Mihai Nita // We don't want to show suggestions for locales with very few regions 21586235d497007ad17ddec7e659fb0e0c36b010745Mihai Nita // (e.g. Romanian, with 2 regions) 21686235d497007ad17ddec7e659fb0e0c36b010745Mihai Nita // So we put a (somewhat) arbitrary limit. 21786235d497007ad17ddec7e659fb0e0c36b010745Mihai Nita // 21886235d497007ad17ddec7e659fb0e0c36b010745Mihai Nita // The initial idea was to make that limit dependent on the screen height. 21986235d497007ad17ddec7e659fb0e0c36b010745Mihai Nita // But that would mean rotating the screen could make the suggestions disappear, 22086235d497007ad17ddec7e659fb0e0c36b010745Mihai Nita // as the number of countries that fits on the screen would be different in portrait 22186235d497007ad17ddec7e659fb0e0c36b010745Mihai Nita // and landscape mode. 22286235d497007ad17ddec7e659fb0e0c36b010745Mihai Nita if (mCountryMode && mLocaleOptions.size() < MIN_REGIONS_FOR_SUGGESTIONS) { 223f1f39cf1936df2d28133e43390f72f3dbb40ffc8Mihai Nita return false; 224f1f39cf1936df2d28133e43390f72f3dbb40ffc8Mihai Nita } 2251808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita return mSuggestionCount != 0 && mSuggestionCount != mLocaleOptions.size(); 2261808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 2271808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 228137b96e3a41edc19a53f7218ef3e53adbfcfd340Mihai Nita /** 229137b96e3a41edc19a53f7218ef3e53adbfcfd340Mihai Nita * Sorts the items in the adapter using a locale-aware comparator. 230137b96e3a41edc19a53f7218ef3e53adbfcfd340Mihai Nita * @param comp The locale-aware comparator to use. 231137b96e3a41edc19a53f7218ef3e53adbfcfd340Mihai Nita */ 2321808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita public void sort(LocaleHelper.LocaleInfoComparator comp) { 2331808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita Collections.sort(mLocaleOptions, comp); 2341808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 2351808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 2361808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita class FilterByNativeAndUiNames extends Filter { 2371808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 2381808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita @Override 2391808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita protected FilterResults performFiltering(CharSequence prefix) { 2401808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita FilterResults results = new FilterResults(); 2411808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 2421808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita if (mOriginalLocaleOptions == null) { 2431808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita mOriginalLocaleOptions = new ArrayList<>(mLocaleOptions); 2441808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 2451808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 2461808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita ArrayList<LocaleStore.LocaleInfo> values; 2471808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita values = new ArrayList<>(mOriginalLocaleOptions); 2481808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita if (prefix == null || prefix.length() == 0) { 2491808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita results.values = values; 2501808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita results.count = values.size(); 2511808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } else { 2521808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita // TODO: decide if we should use the string's locale 2531808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita Locale locale = Locale.getDefault(); 2541808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita String prefixString = LocaleHelper.normalizeForSearch(prefix.toString(), locale); 2551808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 2561808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita final int count = values.size(); 2571808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita final ArrayList<LocaleStore.LocaleInfo> newValues = new ArrayList<>(); 2581808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 2591808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita for (int i = 0; i < count; i++) { 2601808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita final LocaleStore.LocaleInfo value = values.get(i); 2611808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita final String nameToCheck = LocaleHelper.normalizeForSearch( 2621808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita value.getFullNameInUiLanguage(), locale); 2631808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita final String nativeNameToCheck = LocaleHelper.normalizeForSearch( 2641808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita value.getFullNameNative(), locale); 2651808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita if (wordMatches(nativeNameToCheck, prefixString) 2661808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita || wordMatches(nameToCheck, prefixString)) { 2671808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita newValues.add(value); 2681808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 2691808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 2701808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 2711808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita results.values = newValues; 2721808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita results.count = newValues.size(); 2731808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 2741808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 2751808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita return results; 2761808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 2771808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 2781808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita // TODO: decide if this is enough, or we want to use a BreakIterator... 2791808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita boolean wordMatches(String valueText, String prefixString) { 280137b96e3a41edc19a53f7218ef3e53adbfcfd340Mihai Nita // First match against the whole, non-split value 2811808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita if (valueText.startsWith(prefixString)) { 2821808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita return true; 2831808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 2841808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 2851808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita final String[] words = valueText.split(" "); 2861808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita // Start at index 0, in case valueText starts with space(s) 2871808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita for (String word : words) { 2881808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita if (word.startsWith(prefixString)) { 2891808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita return true; 2901808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 2911808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 2921808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 2931808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita return false; 2941808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 2951808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 2961808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita @Override 2971808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita protected void publishResults(CharSequence constraint, FilterResults results) { 2981808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita mLocaleOptions = (ArrayList<LocaleStore.LocaleInfo>) results.values; 2991808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 3001808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita mSuggestionCount = 0; 3011808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita for (LocaleStore.LocaleInfo li : mLocaleOptions) { 3021808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita if (li.isSuggested()) { 3031808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita mSuggestionCount++; 3041808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 3051808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 3061808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 3071808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita if (results.count > 0) { 3081808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita notifyDataSetChanged(); 3091808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } else { 3101808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita notifyDataSetInvalidated(); 3111808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 3121808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 3131808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 3141808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita 3151808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita @Override 3161808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita public Filter getFilter() { 3171808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita return new FilterByNativeAndUiNames(); 3181808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita } 3191808ff7cde452d4831dcfbc6b99afc57f66daedfMihai Nita} 320