Create a new region picker page

1. The region which is selected in region picker will also apply to the first locale.
2. When a user change the first locale, the region of the first locale will be updated to the region picker.

Bug: 385047778
Flag: com.android.settings.flags.regional_preferences_api_enabled
Test: check hsv
Change-Id: I001e0910ce9d1601513ed2f52e6ee30d3551859f
This commit is contained in:
danielwbhuang
2024-12-18 01:58:09 +08:00
parent 7b0e140dc5
commit 09b9d052fc
8 changed files with 521 additions and 0 deletions

View File

@@ -0,0 +1,183 @@
/*
* Copyright (C) 2024 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.regionalpreferences;
import android.content.Context;
import android.os.LocaleList;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;
import com.android.internal.annotations.Initializer;
import com.android.internal.app.LocaleCollectorBase;
import com.android.internal.app.LocaleHelper;
import com.android.internal.app.LocalePicker;
import com.android.internal.app.LocaleStore;
import com.android.internal.app.LocaleStore.LocaleInfo;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.widget.SelectorWithWidgetPreference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.stream.Collectors;
public abstract class RegionPickerBaseListPreferenceController extends BasePreferenceController {
private static final String TAG = "RegionPickerBaseListPreferenceController";
private static final String KEY_SUGGESTED = "suggested";
private PreferenceCategory mPreferenceCategory;
private Set<LocaleInfo> mLocaleList;
private ArrayList<LocaleInfo> mLocaleOptions;
public RegionPickerBaseListPreferenceController(@NonNull Context context,
@NonNull String preferenceKey) {
super(context, preferenceKey);
mLocaleList = getLocaleCollectorController(context).getSupportedLocaleList(null,
false, false);
mLocaleOptions = new ArrayList<>();
mLocaleOptions.ensureCapacity(mLocaleList.size());
}
@Override
@Initializer
public void displayPreference(@NonNull PreferenceScreen screen) {
super.displayPreference(screen);
mPreferenceCategory = screen.findPreference(getPreferenceCategoryKey());
updatePreferences();
}
private void updatePreferences() {
if (mPreferenceCategory == null) {
Log.d(TAG, "updatePreferences, mPreferenceCategory is null");
return;
}
List<LocaleStore.LocaleInfo> result;
LocaleStore.LocaleInfo parentLocale = getParentLocale();
if (parentLocale != null) {
mLocaleList = getLocaleCollectorController(mContext).getSupportedLocaleList(
parentLocale, false, true);
}
mLocaleOptions.clear();
mLocaleOptions.ensureCapacity(mLocaleList.size());
result = getPreferenceCategoryKey().contains(KEY_SUGGESTED)
? getSuggestedLocaleList()
: getSupportedLocaleList();
if (getPreferenceCategoryKey().contains(KEY_SUGGESTED)) {
Locale systemLocale = Locale.getDefault();
LocaleStore.LocaleInfo localeInfo = LocaleStore.getLocaleInfo(systemLocale);
result.add(localeInfo);
}
result = getSortedLocaleList(result);
setupPreference(result);
}
private void setupPreference(List<LocaleStore.LocaleInfo> localeInfoList) {
localeInfoList.stream().forEach(locale -> {
SelectorWithWidgetPreference pref = new SelectorWithWidgetPreference(mContext);
mPreferenceCategory.addPreference(pref);
pref.setTitle(locale.getFullCountryNameNative());
pref.setKey(locale.toString());
if (locale.getLocale().equals(Locale.getDefault())) {
pref.setChecked(true);
} else {
pref.setChecked(false);
}
pref.setOnClickListener(v -> {
switchRegion(locale);
});
});
mPreferenceCategory.setVisible(mPreferenceCategory.getPreferenceCount() > 0);
}
@Override
public int getAvailabilityStatus() {
return AVAILABLE;
}
protected abstract String getPreferenceCategoryKey();
protected abstract LocaleCollectorBase getLocaleCollectorController(Context context);
@Nullable protected abstract LocaleStore.LocaleInfo getParentLocale();
protected List<LocaleStore.LocaleInfo> getSuggestedLocaleList() {
if (mLocaleList != null && !mLocaleList.isEmpty()) {
mLocaleOptions.addAll(mLocaleList.stream()
.filter(localeInfo -> localeInfo.isSuggested())
.collect(Collectors.toList()));
} else {
Log.d(TAG, "Can not get suggested locales because the locale list is null or empty.");
}
return mLocaleOptions;
}
protected List<LocaleStore.LocaleInfo> getSupportedLocaleList() {
if (mLocaleList != null && !mLocaleList.isEmpty()) {
mLocaleOptions.addAll(mLocaleList.stream()
.filter(localeInfo -> !localeInfo.isSuggested())
.collect(Collectors.toList()));
} else {
Log.d(TAG, "Can not get supported locales because the locale list is null or empty.");
}
return mLocaleOptions;
}
private List<LocaleStore.LocaleInfo> getSortedLocaleList(
List<LocaleStore.LocaleInfo> localeInfos) {
final Locale sortingLocale = Locale.getDefault();
final LocaleHelper.LocaleInfoComparator comp =
new LocaleHelper.LocaleInfoComparator(sortingLocale, true);
Collections.sort(localeInfos, comp);
return localeInfos;
}
private void switchRegion(LocaleStore.LocaleInfo localeInfo) {
if (localeInfo.getLocale().equals(Locale.getDefault())) {
return;
}
updateRegion(localeInfo.getLocale().toLanguageTag());
updatePreferences();
}
private void updateRegion(String selectedLanguageTag) {
LocaleList localeList = LocaleList.getDefault();
Locale systemLocale = Locale.getDefault();
Set<Character> extensionKeys = systemLocale.getExtensionKeys();
Locale selectedLocale = Locale.forLanguageTag(selectedLanguageTag);
Locale.Builder builder = new Locale.Builder();
builder.setLocale(selectedLocale);
if (!extensionKeys.isEmpty()) {
for (Character extKey : extensionKeys) {
builder.setExtension(extKey, systemLocale.getExtension(extKey));
}
}
Locale newLocale = builder.build();
Locale[] resultLocales = new Locale[localeList.size()];
resultLocales[0] = newLocale;
for (int i = 1; i < localeList.size(); i++) {
resultLocales[i] = localeList.get(i);
}
LocalePicker.updateLocales(new LocaleList(resultLocales));
}
}