当有很多模块时,Locale 确实有效。
上下文:
我们使用 Crowdin(这个库在上下文之上应用了一个包装器)
当只有一个模块时,该应用程序可以完美运行
使用 Appcompat:1.2
何时更改语言环境有效
但是,当我在 app
中添加一个新模块时,更改语言环境确实有效。 实现项目(":newmodule")
什么时候是单模块:
BaseContext
=CrowdinContextWrapper
什么时候是多模块:
BaseContext
=ContextThemeWrapper
Activity
扩展 BaseActivity
class MainActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
Crowdin.forceUpdate(context = this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
open class BaseActivity : AppCompatActivity() {
override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(Crowdin.wrapContext(Localization.wrap(context = newBase)))
}
}
class Localization(base: Context) : ContextThemeWrapper(base, R.style.AppTheme) {
companion object {
fun wrap(context: Context, language: String = "es", country: String = "MX"): ContextThemeWrapper {
var ctx = context
val config = context.resources.configuration
if (language != "") {
val locale = Locale(language, country)
Locale.setDefault(locale)
config.setLocale(locale)
// Used setLayoutDirection for RTL and LTR
config.setLayoutDirection(locale)
ctx = context.createConfigurationContext(config)
}
return Localization(ctx)
}
}
}
最佳答案
解释
问题与 Appcompat
有关。根据 AppCompat
的版本,有两种不同的修复方法。由于您使用的是 1.2.0
,因此您必须实现该版本。
AppCompatDelegateImpl
最终删除了语言环境,因为本质上是一个 ContextThemeWrapper包裹你的 ContextWrapper .查看实现 @ AppCompatDelegateImpl.java line 368 .也行 388 , 和 480 .
try {
ContextThemeWrapperCompatApi17Impl.applyOverrideConfiguration(
(android.view.ContextThemeWrapper) baseContext, config);
return baseContext;
} catch (IllegalStateException e) {
if (DEBUG) {
Log.d(TAG, "Failed to apply configuration to base context", e);
}
}
解决方法是在您的 Base Activity 中覆盖 getDelegate
,如下所示:
private var baseContextWrappingDelegate: AppCompatDelegate? = null
override fun getDelegate() = baseContextWrappingDelegate ?: BaseContextWrappingDelegate(super.getDelegate()).apply {
baseContextWrappingDelegate = this
}
并且您还需要以下类(参见:Change Locale not work after migrate to Androidx)。
package androidx.appcompat.app
import android.content.Context
import android.content.res.Configuration
import android.os.Bundle
import android.util.AttributeSet
import android.view.MenuInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.view.ActionMode
import androidx.appcompat.widget.Toolbar
class BaseContextWrappingDelegate(private val superDelegate: AppCompatDelegate) : AppCompatDelegate() {
override fun getSupportActionBar() = superDelegate.supportActionBar
override fun setSupportActionBar(toolbar: Toolbar?) = superDelegate.setSupportActionBar(toolbar)
override fun getMenuInflater(): MenuInflater? = superDelegate.menuInflater
override fun onCreate(savedInstanceState: Bundle?) {
superDelegate.onCreate(savedInstanceState)
removeActivityDelegate(superDelegate)
addActiveDelegate(this)
}
override fun onPostCreate(savedInstanceState: Bundle?) = superDelegate.onPostCreate(savedInstanceState)
override fun onConfigurationChanged(newConfig: Configuration?) = superDelegate.onConfigurationChanged(newConfig)
override fun onStart() = superDelegate.onStart()
override fun onStop() = superDelegate.onStop()
override fun onPostResume() = superDelegate.onPostResume()
override fun setTheme(themeResId: Int) = superDelegate.setTheme(themeResId)
override fun <T : View?> findViewById(id: Int) = superDelegate.findViewById<T>(id)
override fun setContentView(v: View?) = superDelegate.setContentView(v)
override fun setContentView(resId: Int) = superDelegate.setContentView(resId)
override fun setContentView(v: View?, lp: ViewGroup.LayoutParams?) = superDelegate.setContentView(v, lp)
override fun addContentView(v: View?, lp: ViewGroup.LayoutParams?) = superDelegate.addContentView(v, lp)
override fun attachBaseContext2(context: Context) = wrap(superDelegate.attachBaseContext2(super.attachBaseContext2(context)))
override fun setTitle(title: CharSequence?) = superDelegate.setTitle(title)
override fun invalidateOptionsMenu() = superDelegate.invalidateOptionsMenu()
override fun onDestroy() {
superDelegate.onDestroy()
removeActivityDelegate(this)
}
override fun getDrawerToggleDelegate() = superDelegate.drawerToggleDelegate
override fun requestWindowFeature(featureId: Int) = superDelegate.requestWindowFeature(featureId)
override fun hasWindowFeature(featureId: Int) = superDelegate.hasWindowFeature(featureId)
override fun startSupportActionMode(callback: ActionMode.Callback) = superDelegate.startSupportActionMode(callback)
override fun installViewFactory() = superDelegate.installViewFactory()
override fun createView(parent: View?, name: String?, context: Context, attrs: AttributeSet): View? = superDelegate.createView(parent, name, context, attrs)
override fun setHandleNativeActionModesEnabled(enabled: Boolean) {
superDelegate.isHandleNativeActionModesEnabled = enabled
}
override fun isHandleNativeActionModesEnabled() = superDelegate.isHandleNativeActionModesEnabled
override fun onSaveInstanceState(outState: Bundle?) = superDelegate.onSaveInstanceState(outState)
override fun applyDayNight() = superDelegate.applyDayNight()
override fun setLocalNightMode(mode: Int) {
superDelegate.localNightMode = mode
}
override fun getLocalNightMode() = superDelegate.localNightMode
private fun wrap(context: Context): Context {
//Put wrapping implementation here
}
}
引用资料
关于android - 添加许多模块时,区域设置的更改确实有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64452898/