语言更改后如何应用更改?
How to apply changes after language change?
我根据自己的喜好使用自定义设置 activity。其中之一是用于选择应用程序语言的 ListPreference
。到目前为止,我可以实现区域设置首选项,但要应用更改,我需要重新启动应用程序。问题是,它不适用于所有 Android 版本。这是我所做的:
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.os.Bundle
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.FragmentActivity
import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
class SettingsActivity : FragmentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_settings)
val toolbar: Toolbar = findViewById(R.id.toolbar_settings)
toolbar.apply {
setNavigationIcon(R.drawable.ic_arrow)
setNavigationOnClickListener { finish() }
title = getString(R.string.settings)
setTitleTextColor(Color.WHITE)
}
supportFragmentManager.beginTransaction().replace(R.id.content, SettingsFragment())
.commit()
}
class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.preferences)
val lang: ListPreference = findPreference("Language")!!
val language = when (LanguageSettings().getLang()) {
"en" -> getString(R.string.en_lang)
"de" -> getString(R.string.de_lang)
else -> getString(R.string.ru_lang)
}
lang.summary = "${getString(R.string.current_language)} $language"
val temp = lang.value
lang.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
val dialogBuilder =
activity?.let { AlertDialog.Builder(it, R.style.AlertDialogLight) }
dialogBuilder!!.setMessage(getString(R.string.restart_txt))
.setPositiveButton(getString(R.string.restart)) { _, _ ->
activity?.let { LanguageSettings().setLocale(it, newValue.toString()) }
restartApp()
}
.setNegativeButton(getString(R.string.cancel)) { dialog, _ ->
lang.value = temp
dialog.cancel()
}
dialogBuilder.create().apply {
show()
}
true
}
}
private fun restartApp() {
val intent = activity!!.packageManager
.getLaunchIntentForPackage(activity!!.packageName)
intent!!.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
activity!!.finish()
startActivity(intent)
}
}
override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(LanguageSettings().onAttach(newBase))
}
}
在棒棒糖下方,重启后应用更改,这意味着重启后应用程序语言已更改。它也适用于 android 10。但这不适用于 Lollipop 和 Marshmallow(目前已测试),但唯一有效的是,仅针对 SettingsActivity 更改语言,其他活动保持不变。可能在 Marshmallow 和 Android X 之间还有其他版本,它也适用。
但是,我想让它适用于所有版本,我的应用程序支持从 16 到最新版本的 SDK。
非常感谢。如果我不是那么精确并且您需要更多信息,请告诉我,我会尽力提供更多信息。同时,请原谅我不完美的英语。
我的LanguageSettings.kt
class:
import android.content.Context
import android.content.res.Configuration
import android.os.Build
import android.util.Log
import androidx.preference.PreferenceManager
import java.util.*
@Suppress("DEPRECATION")
class LanguageSettings {
fun onAttach(context: Context): Context {
return setLocale(context, getPersistedData(context, getLang()!!)!!)
}
fun onAttach(context: Context, defaultLanguage: String): Context {
return setLocale(context, getPersistedData(context, defaultLanguage)!!)
}
fun getLang(): String? {
return when (Locale.getDefault().displayLanguage) {
"English" -> "en"
"Deutsch" -> "de"
"русский" -> "ru"
else -> "en"
}
}
fun setLocale(context: Context, language: String): Context {
persist(context, language)
val configuration: Configuration
val resources = context.resources
val locale =
Locale(language)
Locale.setDefault(locale)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
configuration = context.resources.configuration
configuration.setLocale(locale)
configuration.setLayoutDirection(locale)
return context.createConfigurationContext(configuration)
}
configuration = resources.configuration
configuration.locale = locale
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
configuration.setLayoutDirection(locale)
resources.updateConfiguration(configuration, resources.displayMetrics)
return context
}
private fun getPersistedData(context: Context, defaultLanguage: String): String? {
return PreferenceManager
.getDefaultSharedPreferences(context)
.getString("Language", defaultLanguage)
}
private fun persist(context: Context, language: String) {
PreferenceManager
.getDefaultSharedPreferences(context)
.edit()
.putString("Language", language)
.apply()
}
}
问题:这适用于 Android 4.2-4.4 及以上 7,但不适用于 Android 5.0/5.1/6(并且可能对某些版本也不起作用,没有到目前为止测试所有版本,仅针对上述版本)。
Ans this my MyApp.kt
class that extends Application
is assigned in Manifest file (android:name=".MyApp"
):
class MyApp : Application() {
override fun attachBaseContext(base: Context) {
super.attachBaseContext(LanguageSettings().onAttach(base, "en"))
}
}
我在测试了很多不同的情况后找到了解决方案:
private fun setLocale(context: Context, language: String): Context {
val configuration: Configuration
val resources = context.resources
val locale = when (language) {
"de" -> Locale("de", "DE")
"ru" -> Locale("ru", "RU")
"en" -> Locale("en", "US")
else -> Locale("en", "US")
}
Locale.setDefault(locale)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
configuration = context.resources.configuration
configuration.setLocale(locale)
configuration.setLayoutDirection(locale)
return context.createConfigurationContext(configuration)
}
configuration = resources.configuration
configuration.locale = locale
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
configuration.setLayoutDirection(locale)
resources.updateConfiguration(configuration, resources.displayMetrics)
return context
}
这在 Kotlin 中很适合我。
我根据自己的喜好使用自定义设置 activity。其中之一是用于选择应用程序语言的 ListPreference
。到目前为止,我可以实现区域设置首选项,但要应用更改,我需要重新启动应用程序。问题是,它不适用于所有 Android 版本。这是我所做的:
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.os.Bundle
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.FragmentActivity
import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
class SettingsActivity : FragmentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_settings)
val toolbar: Toolbar = findViewById(R.id.toolbar_settings)
toolbar.apply {
setNavigationIcon(R.drawable.ic_arrow)
setNavigationOnClickListener { finish() }
title = getString(R.string.settings)
setTitleTextColor(Color.WHITE)
}
supportFragmentManager.beginTransaction().replace(R.id.content, SettingsFragment())
.commit()
}
class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.preferences)
val lang: ListPreference = findPreference("Language")!!
val language = when (LanguageSettings().getLang()) {
"en" -> getString(R.string.en_lang)
"de" -> getString(R.string.de_lang)
else -> getString(R.string.ru_lang)
}
lang.summary = "${getString(R.string.current_language)} $language"
val temp = lang.value
lang.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
val dialogBuilder =
activity?.let { AlertDialog.Builder(it, R.style.AlertDialogLight) }
dialogBuilder!!.setMessage(getString(R.string.restart_txt))
.setPositiveButton(getString(R.string.restart)) { _, _ ->
activity?.let { LanguageSettings().setLocale(it, newValue.toString()) }
restartApp()
}
.setNegativeButton(getString(R.string.cancel)) { dialog, _ ->
lang.value = temp
dialog.cancel()
}
dialogBuilder.create().apply {
show()
}
true
}
}
private fun restartApp() {
val intent = activity!!.packageManager
.getLaunchIntentForPackage(activity!!.packageName)
intent!!.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
activity!!.finish()
startActivity(intent)
}
}
override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(LanguageSettings().onAttach(newBase))
}
}
在棒棒糖下方,重启后应用更改,这意味着重启后应用程序语言已更改。它也适用于 android 10。但这不适用于 Lollipop 和 Marshmallow(目前已测试),但唯一有效的是,仅针对 SettingsActivity 更改语言,其他活动保持不变。可能在 Marshmallow 和 Android X 之间还有其他版本,它也适用。
但是,我想让它适用于所有版本,我的应用程序支持从 16 到最新版本的 SDK。
非常感谢。如果我不是那么精确并且您需要更多信息,请告诉我,我会尽力提供更多信息。同时,请原谅我不完美的英语。
我的LanguageSettings.kt
class:
import android.content.Context
import android.content.res.Configuration
import android.os.Build
import android.util.Log
import androidx.preference.PreferenceManager
import java.util.*
@Suppress("DEPRECATION")
class LanguageSettings {
fun onAttach(context: Context): Context {
return setLocale(context, getPersistedData(context, getLang()!!)!!)
}
fun onAttach(context: Context, defaultLanguage: String): Context {
return setLocale(context, getPersistedData(context, defaultLanguage)!!)
}
fun getLang(): String? {
return when (Locale.getDefault().displayLanguage) {
"English" -> "en"
"Deutsch" -> "de"
"русский" -> "ru"
else -> "en"
}
}
fun setLocale(context: Context, language: String): Context {
persist(context, language)
val configuration: Configuration
val resources = context.resources
val locale =
Locale(language)
Locale.setDefault(locale)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
configuration = context.resources.configuration
configuration.setLocale(locale)
configuration.setLayoutDirection(locale)
return context.createConfigurationContext(configuration)
}
configuration = resources.configuration
configuration.locale = locale
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
configuration.setLayoutDirection(locale)
resources.updateConfiguration(configuration, resources.displayMetrics)
return context
}
private fun getPersistedData(context: Context, defaultLanguage: String): String? {
return PreferenceManager
.getDefaultSharedPreferences(context)
.getString("Language", defaultLanguage)
}
private fun persist(context: Context, language: String) {
PreferenceManager
.getDefaultSharedPreferences(context)
.edit()
.putString("Language", language)
.apply()
}
}
问题:这适用于 Android 4.2-4.4 及以上 7,但不适用于 Android 5.0/5.1/6(并且可能对某些版本也不起作用,没有到目前为止测试所有版本,仅针对上述版本)。
Ans this my MyApp.kt
class that extends Application
is assigned in Manifest file (android:name=".MyApp"
):
class MyApp : Application() {
override fun attachBaseContext(base: Context) {
super.attachBaseContext(LanguageSettings().onAttach(base, "en"))
}
}
我在测试了很多不同的情况后找到了解决方案:
private fun setLocale(context: Context, language: String): Context {
val configuration: Configuration
val resources = context.resources
val locale = when (language) {
"de" -> Locale("de", "DE")
"ru" -> Locale("ru", "RU")
"en" -> Locale("en", "US")
else -> Locale("en", "US")
}
Locale.setDefault(locale)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
configuration = context.resources.configuration
configuration.setLocale(locale)
configuration.setLayoutDirection(locale)
return context.createConfigurationContext(configuration)
}
configuration = resources.configuration
configuration.locale = locale
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
configuration.setLayoutDirection(locale)
resources.updateConfiguration(configuration, resources.displayMetrics)
return context
}
这在 Kotlin 中很适合我。