遇到这样的问题。在我的应用程序中,我实现了本地化,但它应该与系统的语言环境分开为我工作。我在教程的帮助下编写了 LocaleHelper 类
import android.content.Context
import android.os.Build
import com.example.core.utils.preferences.AppSharedPreferences
import timber.log.Timber
import java.util.*
class LocaleHelper(private val appPreferences: AppSharedPreferences) {
fun onAttach(context: Context): Context? {
val lang = getPersistedData(Locale.getDefault().language)
Timber.d("Locale/LocaleHelper.onAttach.lang = $lang")
return setLocale(context, lang!!)
}
fun onAttach(context: Context, locale: String): Context? {
val lang = getPersistedData(locale)
return setLocale(context, lang!!)
}
fun setLocale(context: Context, language: String): Context? {
persist(language)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return updateResources(context, language)
}
return updateResourcesLegacy(context, language)
}
private fun getPersistedData(locale: String): String? {
Timber.d("Locale/LocaleHelper.getPersistData.lang = $locale")
return appPreferences.loadChangingByUserLocale(locale)
}
private fun persist(language: String) {
appPreferences.saveChangingByUserLocale(language)
}
private fun updateResources(context: Context, language: String): Context? {
val appLocale = Locale(language)
val configuration = context.resources.configuration
Locale.setDefault(appLocale)
configuration.apply {
setLocale(appLocale)
setLayoutDirection(appLocale)
}
return context.createConfigurationContext(configuration)
}
@Suppress("DEPRECATION")
private fun updateResourcesLegacy(context: Context, language: String): Context? {
val appLocale = Locale(language)
val resource = context.resources
val configuration = resource.configuration
Locale.setDefault(appLocale)
configuration.locale = appLocale
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
configuration.setLayoutDirection(appLocale)
}
resource.updateConfiguration(configuration, resource.displayMetrics)
return context
}
}
在主页上,我制作了一个下拉列表,点击即可打开
私人乐趣 preparePopupWindowLangs(): PopupWindow? { val popup = PopupWindow(view!!.context).apply { width = 250 height = WindowManager.LayoutParams.WRAP_CONTENT isOutsideTouchable = true isFocusable = true contentView = contentList() } logger.preparePopupWindow() 返回弹出窗口 }
private fun contentList(): ListView {
val localesAdapter = LanguagesPopupAdapter(context!!, prepareLocalesList(viewModel.localesNames))
localesAdapter.notifyDataSetChanged()
val listView = ListView(context).apply {
adapter = localesAdapter
onItemClickListener = popupOnItemClick()
}
return listView
}
private fun prepareLocalesList(@StringRes array: Array<Int>): List<String> {
val locales: MutableList<String> = mutableListOf()
array.forEachIndexed { index, locale ->
locales.add(index, resources.getString(locale))
}
return locales
}
private fun popupOnItemClick(): OnItemClickListener {
val itemClick = OnItemClickListener { parent, view, position, id ->
val fadeInAnimation: Animation =
AnimationUtils.loadAnimation(context, R.anim.fragment_fade_enter)
fadeInAnimation.duration = 10
view!!.startAnimation(fadeInAnimation)
val selectedItemText = view.findViewById<TextView>(R.id.language_tv).text.toString()
langs_popup.text = selectedItemText
popup!!.dismiss()
changeLocale(viewModel.localesIndexes[position])
}
return itemClick
}
通过从列表中选择,我更改了文本
private fun changeTextAfterLanguageSelection(lang: String) {
val context = viewModel.localeHelper.setLocale(context!!, lang)
val resources = context!!.resources
login_tv.text = resources.getString(R.string.field_header_login)
login_et.hint = resources.getString(R.string.hint_login)
password_tv.text = resources.getString(R.string.field_header_password)
password_et.hint = resources.getString(R.string.hint_password)
auth_progress_button.setButtonName(context, R.string.btn_enter)
prepareLocalesList(viewModel.localesNames)
setPopupTitleText()
}
我还添加了一种方法来更改片段中的文本
override fun onAttach(context: Context) {
super.onAttach(viewModel.localeHelper.onAttach(context)!!)
}
添加了在活动中为应用程序设置区域设置的方法
override fun attachBaseContext(newBase: Context?) {
super.attachBaseContext(localeHelper.onAttach(newBase!!, appPreferences.loadChangingByUserLocale("ru")!!)))
}
结果,我得到以下信息:在具有 API 22 的模拟器中,一切正常,但已经在 API 29 上,当切换到另一个片段时,不执行翻译,而只执行应用程序时的语言环境已推出作品。我知道选择语言时可以选择重新启动活动,但这种方法不适合我的任务。我正在实施 SingleActivity 技术。