#android #android-layout #android-fragments #locale
#Android #android-макет #android-фрагменты #язык
Вопрос:
Когда пользователь меняет язык, я выполняю следующий код, он отлично работает для текущего фрагмента в действии, но если я перехожу к другому фрагменту, он частично обновляет язык, некоторые строки обновляются и показывают старый язык, и, самое главное, дата не меняется во внутренних фрагментах и других действиях.
Я тестировал это в nougat, marshmallow и oreo, и это происходит во всех ОС.
Когда пользователь меняет язык, я выполняю следующее.
LocaleHelper.setLocale(getApplicationContext(), language);
recreate();
LocalHelper
public static Context setLocale(Context context, String language) {
persist(context, language);
Log.d("LocaleSet", language);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return updateResources(context, language);
}
return updateResourcesLegacy(context, language);
}
Метод для post marshmallow OS.
@TargetApi(Build.VERSION_CODES.N)
private static Context updateResources(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Configuration configuration = context.getResources().getConfiguration();
configuration.setLocale(locale);
return context.createConfigurationContext(configuration);
}
Предварительная нуга
@SuppressWarnings("deprecation")
private static Context updateResourcesLegacy(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
configuration.locale = locale;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
configuration.setLayoutDirection(locale);
}
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
return context;
}
В каждом действии я выполняю следующий код.
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(LocaleHelper.onAttach(base, LocaleHelper.getLanguage(base)));
}
Mainfest
<application
android:name=".GlobalApplication"
android:allowBackup="false"
android:icon="@mipmap/app_icon"
android:label="@string/app_name"
android:roundIcon="@mipmap/app_icon"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:windowSoftInputMode="adjustPan"
tools:replace="android:allowBackup">
<activity
android:name=".activities.homeactivity.HomeActivity"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:configChanges="locale"
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name=".activities.profilepageactivity.ProfilePageActivity"
android:label="@string/title_activity_profile_page"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.NoActionBar" />
Комментарии:
1. Можете ли вы также добавить свой
AndroidManifest.xml
?2. @madlymad: я обновил вопрос и добавил файл манифеста, пожалуйста, проверьте.
3. Вы пробовали это без указания
android:configChanges="locale"
в манифесте?4. Это может быть связано с тем, как вы форматируете свои даты
5. Большое спасибо, я использовал новый SimpleDateFormat(DatePattern, new Locale(«язык»)) , и теперь его дата загрузки в порядке.. Пожалуйста, добавьте свое решение в качестве ответа, я приму его. не могли бы вы также указать мне, как
android:configChanges
это исправить.
Ответ №1:
Я предполагаю, что вы используете этот подход. Там, где не предложено никаких изменений в AndroidManifest.xml
so android:configChanges="locale"
, это может привести к неправильному поведению, которое вы определили.
Для форматирования даты вы должны учитывать, что ваше приложение не использует Locale.getDefault()
, а что-то другое, что определяется пользователем и вашим LocaleHelper
механизмом.
Некоторые дополнительные сведения об изменении конфигурации
Это android:configChanges
означает, что вы не хотите, чтобы система воссоздавала вашу активность при возникновении одного из предоставленных атрибутов. В вашем случае locale
.
С точки зрения разработки с таким подходом, чтобы правильно обработать эту опцию в манифесте, вы должны реализовать
@Override
public void onConfigurationChanged(Configuration newConfig) {
// refresh your views here
super.onConfigurationChanged(newConfig);
}
а затем выполните свою собственную обработку. То, что вам не требовалось в вашем случае.
Ответ №2:
Класс приложения, который расширен в файле манифеста.
package com.example.languageapplication;
import android.content.Context;
public class Application extends android.app.Application {
private static Application applicationInstance;
public static synchronized Application getInstance() {
return applicationInstance;
}
@Override
public void onCreate() {
super.onCreate();
applicationInstance = this;
}
public void initAppLanguage(Context context) {
LocaleUtils.initialize(context, LocaleUtils.getSelectedLanguageId());
}
}
Locale использует класс для заданного языка в общих настройках и обновляет конфигурацию для заданного языка
public class LocaleUtils {
public static final String ENGLISH = "en";
public static final String FRENCH = "fr";
public static final String SPANISH = "es";
public static void initialize(Context context, @LocaleDef String defaultLanguage) {
setLocale(context, defaultLanguage);
}
public static boolean setLocale(Context context, @LocaleDef String language) {
return updateResources(context, language);
}
private static boolean updateResources(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
context.createConfigurationContext(configuration);
configuration.locale = locale;
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
return true;
}
@Retention(RetentionPolicy.SOURCE)
@StringDef({ENGLISH, FRENCH, SPANISH})
public @interface LocaleDef {
String[] SUPPORTED_LOCALES = {ENGLISH, FRENCH, SPANISH};
}
private static SharedPreferences getDefaultSharedPreference(Context context) {
if (PreferenceManager.getDefaultSharedPreferences(Application.getInstance().getApplicationContext()) != null)
return PreferenceManager.getDefaultSharedPreferences(Application.getInstance().getApplicationContext());
else
return null;
}
public static void setSelectedLanguageId(String id){
final SharedPreferences prefs = getDefaultSharedPreference(Application.getInstance().getApplicationContext());
SharedPreferences.Editor editor = prefs.edit();
editor.putString("app_language_id", id);
editor.apply();
}
public static String getSelectedLanguageId(){
return getDefaultSharedPreference(Application.getInstance().getApplicationContext())
.getString("app_language_id", "en");
}
}
установите язык при нажатии кнопки в другом действии и перезапустите действие запуска
public class setLaunguageActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
}
public void setEnglish(View view) {
LocaleUtils.setSelectedLanguageId("en");
Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage(getBaseContext().getPackageName());
startActivity(i);
}
public void setFrance(View view) {
LocaleUtils.setSelectedLanguageId("fr");
Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage(getBaseContext().getPackageName());
startActivity(i);
}
}
Инициализируйте класс приложения в основном действии следующим образом
public class MainActivity extends AppCompatActivity {
TextView textInfo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Application.getInstance().initAppLanguage(this);
setContentView(R.layout.activity_main);
}
этот код работает для меня