Fre*_*red 21 android android-activity android-support-library androidx
我有一个支持多种语言的旧项目。我想升级支持库和目标平台,在迁移到Androidx之前,一切正常,但现在更改语言无效!
我使用此代码更改App的默认语言环境
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);
}
Run Code Online (Sandbox Code Playgroud)
并在每个活动上通过attachBaseContext这样的覆盖调用此方法:
@Override
protected void attachBaseContext(Context newBase)
{
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
String language = preferences.getString(SELECTED_LANGUAGE, "fa");
super.attachBaseContext(updateResources(newBase, language));
}
Run Code Online (Sandbox Code Playgroud)
我尝试其他方法来获取字符串,但我注意到了吗?getActivity().getBaseContext().getString工作,而getActivity().getString不是工作。即使以下代码也不起作用,并且始终app_name在默认资源string.xml中显示vlaue。
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name"/>
Run Code Online (Sandbox Code Playgroud)
我在https://github.com/Freydoonk/LanguageTest中共享示例代码
也getActivity()..getResources().getIdentifier行不通,总是返回0!
010*_*101 36
基本上,在后台发生的事情是,当您在中正确设置了配置后attachBaseContext,AppCompatDelegateImpl然后它将覆盖该配置,并将其覆盖为完全没有区域设置的全新配置:
final Configuration conf = new Configuration();
conf.uiMode = newNightMode | (conf.uiMode & ~Configuration.UI_MODE_NIGHT_MASK);
try {
...
((android.view.ContextThemeWrapper) mHost).applyOverrideConfiguration(conf);
handled = true;
} catch (IllegalStateException e) {
...
}
Run Code Online (Sandbox Code Playgroud)
在最新(尚未发布)的代码中,此问题实际上已得到修复:新配置是基本上下文配置的深层副本。
final Configuration conf = new Configuration(baseConfiguration);
conf.uiMode = newNightMode | (conf.uiMode & ~Configuration.UI_MODE_NIGHT_MASK);
try {
...
((android.view.ContextThemeWrapper) mHost).applyOverrideConfiguration(conf);
handled = true;
} catch (IllegalStateException e) {
...
}
Run Code Online (Sandbox Code Playgroud)
在此版本发布之前,可以手动执行完全相同的操作。要继续使用1.1.0版,请在您的下面添加attachBaseContext:
Kotlin解决方案
override fun applyOverrideConfiguration(overrideConfiguration: Configuration?) {
if (overrideConfiguration != null) {
val uiMode = overrideConfiguration.uiMode
overrideConfiguration.setTo(baseContext.resources.configuration)
overrideConfiguration.uiMode = uiMode
}
super.applyOverrideConfiguration(overrideConfiguration)
}
Run Code Online (Sandbox Code Playgroud)
Java解决方案
@Override
public void applyOverrideConfiguration(Configuration overrideConfiguration) {
if (overrideConfiguration != null) {
int uiMode = overrideConfiguration.uiMode;
overrideConfiguration.setTo(getBaseContext().getResources().getConfiguration());
overrideConfiguration.uiMode = uiMode;
}
super.applyOverrideConfiguration(overrideConfiguration);
}
Run Code Online (Sandbox Code Playgroud)
此代码不正是相同的Configuration(baseConfiguration)引擎盖下做,而是因为我们正在做这之后的AppCompatDelegate已设置正确的uiMode,我们必须确保采取覆盖uiMode到我们修复它之后,所以我们不会失去黑暗/灯光模式设置。
Jac*_*bos 13
与夜间模式相关的新应用程序兼容库中存在一个问题,该问题导致覆盖 android 21 到 25 上的配置。这可以通过在调用此公共函数时应用您的配置来解决:
public void applyOverrideConfiguration(配置覆盖配置
对我来说,这个小技巧通过将设置从覆盖的配置复制到我的配置中起作用了,但是你可以做任何你想做的事情。最好将您的语言逻辑重新应用到新配置中以最大程度地减少错误
@Override
public void applyOverrideConfiguration(Configuration overrideConfiguration) {
if (Build.VERSION.SDK_INT >= 21&& Build.VERSION.SDK_INT <= 25) {
//Use you logic to update overrideConfiguration locale
Locale locale = getLocale()//your own implementation here;
overrideConfiguration.setLocale(locale);
}
super.applyOverrideConfiguration(overrideConfiguration);
}
Run Code Online (Sandbox Code Playgroud)
我正在使用 "androidx.appcompat:appcompat:1.3.0-alpha01" 但我想它也适用于Version 1.2.0。
以下代码基于Android 代码搜索。
import android.content.Context
import android.content.res.Configuration
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import java.util.*
open class MyBaseActivity :AppCompatActivity(){
override fun attachBaseContext(newBase: Context?) {
super.attachBaseContext(newBase)
val config = Configuration()
applyOverrideConfiguration(config)
}
override fun applyOverrideConfiguration(newConfig: Configuration) {
super.applyOverrideConfiguration(updateConfigurationIfSupported(newConfig))
}
open fun updateConfigurationIfSupported(config: Configuration): Configuration? {
// Configuration.getLocales is added after 24 and Configuration.locale is deprecated in 24
if (Build.VERSION.SDK_INT >= 24) {
if (!config.locales.isEmpty) {
return config
}
} else {
if (config.locale != null) {
return config
}
}
// Please Get your language code from some storage like shared preferences
val languageCode = "fa"
val locale = Locale(languageCode)
if (locale != null) {
// Configuration.setLocale is added after 17 and Configuration.locale is deprecated
// after 24
if (Build.VERSION.SDK_INT >= 17) {
config.setLocale(locale)
} else {
config.locale = locale
}
}
return config
}
}
Run Code Online (Sandbox Code Playgroud)
最后,我在我的应用程序中发现了问题。将项目迁移到我的项目的Androidx依赖项时,更改如下:
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.appcompat:appcompat:1.1.0-alpha03'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.google.android.material:material:1.1.0-alpha04'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0-alpha02'
}
Run Code Online (Sandbox Code Playgroud)
可以看到,版本androidx.appcompat:appcompat是1.1.0-alpha03当我将其更改为最新的稳定版本时1.0.2,我的问题已解决并且更改语言正常工作。
我在Maven存储库中找到了appcompat库的最新稳定版本。我还将其他库更改为最新的稳定版本。
现在我的应用程序依赖项如下所示:
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.google.android.material:material:1.0.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}
Run Code Online (Sandbox Code Playgroud)
迟到的答案,但我认为可能会有所帮助。截至androidx.appcompat:appcompat:1.2.0-beta01 0101100101覆盖的解决方案applyOverrideConfiguration不再适用于我。相反,在 then overriden 中attacheBaseContext,您必须调用 theapplyOverrideConfiguration() 而不覆盖 it。
override fun attachBaseContext(newBase: Context) {
val newContext = LocaleHelper.getUpdatedContext(newBase)
super.attachBaseContext(newContext)
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1){
applyOverrideConfiguration(newContext.resources.configuration)
}
}
Run Code Online (Sandbox Code Playgroud)
遗憾的是他的解决方案仅适用于 1.1.0。根据我的研究,这应该已经正式修复了。奇怪的是,这个错误仍然存在。我知道我使用的是测试版,但对于想要使用最新版本的人来说,这个解决方案对我来说是有效的。在模拟器 api 级别 21-25 上测试。在那个 api 级别之上,你不必担心它。
最后我得到了 locate 的解决方案,在我的情况下,实际问题是bundle apk 因为它拆分了 locate 文件。在bundle apk默认情况下,所有的分裂将会产生。但是在build.gradle文件的 android 块中,您可以声明将生成哪些拆分。
bundle {
language {
// Specifies that the app bundle should not support
// configuration APKs for language resources. These
// resources are instead packaged with each base and
// dynamic feature APK.
enableSplit = false
}
}
Run Code Online (Sandbox Code Playgroud)
将此代码添加到androidbuild.gradle文件块后,我的问题得到解决。
该androidx.appcompat:appcompat:1.1.0漏洞还可以通过简单地调用解决getResources()中Activity.applyOverrideConfiguration()
@Override public void
applyOverrideConfiguration(Configuration cfgOverride)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP &&
Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
// add this to fix androidx.appcompat:appcompat 1.1.0 bug
// which happens on Android 6.x ~ 7.x
getResources();
}
super.applyOverrideConfiguration(cfgOverride);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1900 次 |
| 最近记录: |