一:创建不同语言的strings.xml
1.1 选中res,右键选择Android Resource Directory => Locale => >> 选择你需要的语言
1.2 将values下的strings.xml复制到对应语言下的values下
1.3 将不同strings.xml中的内容改成对应的语言文字,不同strings.xml中同一个内容的name是相同的
1.4 在布局文件或者代码中引用strings.xml里的内容
我选择了英文和繁体中文,创建好后如下图所示
二:代码切换语言
android N以下,需要在application的onCreate里切换Locale,N及以上,在Activity的attachBaseContext去切换即可
实现代码如下
2.1 创建LocaleUtils文件
/**
* 如果是7.0以下,我们需要调用changeAppLanguage方法,
* 如果是7.0及以上系统,直接把我们想要切换的语言类型保存起来,在baseActivity中切换
* 然后重新启动MainActivity
* @param locale
* @param context
*/
public static void changeAppLanguage(Locale locale,Context context){
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
Configuration configuration = context.getResources().getConfiguration();
if ((Build.VERSION.SDK_INT < Build.VERSION_CODES.N)){
configuration.setLocale(locale);
}
context.getResources().updateConfiguration(configuration,metrics);
HawkUtil.INSTANCE.saveLocale(locale);
}
public static Context attachBaseContext(Context context){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return updateResources(context);
}
return context;
}
@RequiresApi(Build.VERSION_CODES.N)
private static Context updateResources(Context context) {
Locale locale = HawkUtil.INSTANCE.getLocale();
Configuration configuration = context.getResources().getConfiguration();
configuration.setLocale(locale);
configuration.setLocales(new LocaleList(locale));
return context.createConfigurationContext(configuration);
}
2.2 自定义Application
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
Hawk.init(this).build()
/**
* 对于7.0以下,需要在Application创建的时候进行语言切换
*/
val locale = HawkUtil.getLocale()
LocaleUtils.changeAppLanguage(locale,this)
}
/**
* 系统切换语言时,会回调次方法
*/
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
val locale = HawkUtil.getLocale()
Locale.setDefault(locale)
LocaleUtils.changeAppLanguage(locale,this)
}
}
2.3 创建BaseActivity
open class BaseActivity : AppCompatActivity() {
/**
* 此方法先于 onCreate()方法执行
* @param newBase
*/
override fun attachBaseContext(newBase: Context?) {
/**
* attach对应语言环境下的context
*/
super.attachBaseContext(LocaleUtils.attachBaseContext(newBase))
}
}
2.4 将MainActivity继承BaseActivity
class MainActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<Button>(R.id.btn_simplified).setOnClickListener {
switchAppLanguage(Locale.SIMPLIFIED_CHINESE)
}
findViewById<Button>(R.id.btn_traditional).setOnClickListener {
switchAppLanguage(Locale.TRADITIONAL_CHINESE)
}
findViewById<Button>(R.id.btn_english).setOnClickListener {
switchAppLanguage(Locale.US)
}
}
private fun switchAppLanguage(locale: Locale){
LocaleUtils.changeAppLanguage(locale,this)
val intent = Intent(this, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(intent)
}
}
上面的代码代码只是可以切换语言,只适用于单页面,Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK会清掉任务栈里的activity实例,再将MainActivity的实例添加到新的任务栈。
在我实际的项目中,登录页面也可以进入到切换语言页面,而所有需要登录后才能操作的地方都可以进入到登录页,这样就需要保留任务栈。这时就不能直接用 2.4中switchAppLanguage()的方法了
在2.3中,在baseActivity中重写attachBaseContext(), 在切换语言后,已启动的activity会回调次方法。新启动的activity也会在onCreate()回调前先回调attachBaseContext(),所以需要考虑怎么让已有任务栈里的activity回调attachBaseContext()
我的做法是 自己维护一个任务栈,选择了相应的语言点击保存后。遍历自己维护的任务栈,调用activity的recreate()方法,代码如下
private fun finishPage(){
//当前页面不recreate,不然会有闪退那样的闪一下
AppManager.getInstance().activityStack.forEach {
if (it !is SelectLanguageActivity){
it.recreate()
}
}
//别的activity recreate完,finish掉当前页面,返回到进入切换语言的页面
finish()
}
注意,调用activity的recreate(),activity及view需要做好状态保存和恢复。
上面这样切换,在Android7的系统上会有问题
现在暂时的做法是在BaseActivity上重写getResources()方法
具体看如下代码
@Override
public Resources getResources() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && Build.VERSION.SDK_INT < Build.VERSION_CODES.O){
Context cc = LocaleUtil.INSTANCE.changeLang(getApplicationContext());
return cc.getResources();
}else {
return super.getResources();
}
}
@Override
protected void attachBaseContext(Context newBase) {
Context cc = LocaleUtil.INSTANCE.changeLang(newBase);
super.attachBaseContext(cc);
}
LogcaleUtil.changeLang()的代码如下文章来源:https://www.toymoban.com/news/detail-400577.html
fun changeLang(context: Context): Context{
val res = context.resources
val config = res.configuration
val locale: Locale = HawkUtil.getLocale()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
config.setLocale(locale)
config.setLocales(LocaleList(locale))
}else{
config.locale = locale
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1){
config.setLayoutDirection(locale)
return ContextWrapper(context.createConfigurationContext(config))
}else{
context.resources.updateConfiguration(config,res.displayMetrics)
return ContextWrapper(context)
}
}
打包aab发布到google play上,用户下载下来切换多语言可能会失败
设置多语言不分包处理可解决
在app级gradle中,Android-defuultConfig中添加如下代码文章来源地址https://www.toymoban.com/news/detail-400577.html
bundle {
language {
//多语言不分包处理
enableSplit = false
}
density {
// This property is set to true by default.
enableSplit = true
}
abi {
// This property is set to true by default.
enableSplit = true
}
}
到了这里,关于android 应用内切换语言的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!