查看: 1341|回复: 0

[手机开发] Android实现应用内置语言切换功能

发表于 2017-8-1 08:00:04

一、需求

有时候应用需要在内部切换语言但又不影响系统的语言,比如是应用现在是中文的,系统语言也是中文的,我把应用的切换成英文显示后系统语言还是中文的,系统语言切换后也不会被改变,还有就是有些机的系统是被改造精简过的,比如有些国产机的系统的语言就被精简剩中文和英文。支付宝、微信、Top Story都有在应用内部设置语言切换这样的功能。

二、实现效果

先看看实现效果吧。

三、实现

(一)添加多种语言的资源文件夹及文件

我这默认是英语再添加了个俄文(Google翻译的)和中文。

values/strings.xml

  1. <resources>
  2. <string name="app_name">SwitchLanguage</string>
  3. <string name="helloworld">Hello World!</string>
  4. <string name="language">Eng</string>
  5. <string name="english">English</string>
  6. <string name="chinese">中文</string>
  7. <string name="russian">русский</string>
  8. <string name="secondact">Second Activity</string>
  9. </resources>
复制代码

values-ru/strings.xml

  1. <resources>
  2. <string name="app_name">Переключение язык</string>
  3. <string name="helloworld">привет мир!</string>
  4. <string name="language">русский</string>
  5. <string name="secondact">второй активность</string>
  6. </resources>
复制代码

values-zh/strings.xml

  1. <resources>
  2. <string name="app_name">切换语言</string>
  3. <string name="helloworld">你好 世界!</string>
  4. <string name="language">中文</string>
  5. <string name="secondact">第二屏</string>
  6. </resources>
复制代码

(二)布局文件
activity_main.xml

默认标题栏的文字是切换语言后是不会被改变的,使用Toobar替换掉就可以了。

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout
  3. android:id="@+id/activity_main"
  4. xmlns:android="http://schemas.android.com/apk/res/android"
  5. xmlns:tools="http://schemas.android.com/tools"
  6. android:layout_width="match_parent"
  7. android:layout_height="match_parent"
  8. android:orientation="vertical"
  9. tools:context="com.ce.switchlanguage.MainActivity"
  10. xmlns:app="http://schemas.android.com/apk/res-auto">
  11. <android.support.design.widget.AppBarLayout
  12. android:layout_height="wrap_content"
  13. android:layout_width="match_parent"
  14. android:theme="@style/AppTheme.AppBarOverlay">
  15. <android.support.v7.widget.Toolbar
  16. android:id="@+id/toolbar"
  17. android:layout_width="match_parent"
  18. android:layout_height="?attr/actionBarSize"
  19. android:background="?attr/colorPrimary"
  20. app:popupTheme="@style/AppTheme.PopupOverlay"
  21. app:title="@string/app_name"/>
  22. </android.support.design.widget.AppBarLayout>
  23. <TextView
  24. android:layout_width="wrap_content"
  25. android:layout_height="wrap_content"
  26. android:text="@string/helloworld"/>
  27. <Button
  28. android:id="@+id/change"
  29. android:layout_width="wrap_content"
  30. android:layout_height="wrap_content"
  31. android:layout_gravity="center"
  32. android:text="@string/language"/>
  33. </LinearLayout>
复制代码

styles.xml

设置语言后需要重启下activity,启动会有个效果,使用windowDisablePreview屏蔽掉它。

  1. <resources>
  2. <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
  3. <item name="colorPrimary">@color/colorPrimary</item>
  4. <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
  5. <item name="colorAccent">@color/colorAccent</item>
  6. <item name="windowActionBar">false</item>
  7. <item name="windowNoTitle">true</item>
  8. <item name="android:windowDisablePreview">true</item>
  9. </style>
  10. <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar"/>
  11. <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Dark"/>
  12. </resources>
复制代码

main_menu.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <menu xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto">
  4. <item android:id="@+id/chinese" android:title="@string/chinese" app:showAsAction="never" />
  5. <item android:id="@+id/english" android:title="@string/english" app:showAsAction="never" />
  6. <item android:id="@+id/russian" android:title="@string/russian" app:showAsAction="never" />
  7. </menu>
复制代码

(三)LocaleUtils

  1. package com.ce.switchlanguage;
  2. import android.content.Context;
  3. import android.content.SharedPreferences;
  4. import android.content.res.Configuration;
  5. import android.os.Build;
  6. import android.util.DisplayMetrics;
  7. import com.google.gson.Gson;
  8. import java.util.Locale;
  9. public class LocaleUtils {
  10. /**
  11. * 中文
  12. */
  13. public static final Locale LOCALE_CHINESE = Locale.CHINESE;
  14. /**
  15. * 英文
  16. */
  17. public static final Locale LOCALE_ENGLISH = Locale.ENGLISH;
  18. /**
  19. * 俄文
  20. */
  21. public static final Locale LOCALE_RUSSIAN = new Locale("ru");
  22. /**
  23. * 保存SharedPreferences的文件名
  24. */
  25. private static final String LOCALE_FILE = "LOCALE_FILE";
  26. /**
  27. * 保存Locale的key
  28. */
  29. private static final String LOCALE_KEY = "LOCALE_KEY";
  30. /**
  31. * 获取用户设置的Locale
  32. * @param pContext Context
  33. * @return Locale
  34. */
  35. public static Locale getUserLocale(Context pContext) {
  36. SharedPreferences _SpLocale = pContext.getSharedPreferences(LOCALE_FILE, Context.MODE_PRIVATE);
  37. String _LocaleJson = _SpLocale.getString(LOCALE_KEY, "");
  38. return jsonToLocale(_LocaleJson);
  39. }
  40. /**
  41. * 获取当前的Locale
  42. * @param pContext Context
  43. * @return Locale
  44. */
  45. public static Locale getCurrentLocale(Context pContext) {
  46. Locale _Locale;
  47. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //7.0有多语言设置获取顶部的语言
  48. _Locale = pContext.getResources().getConfiguration().getLocales().get(0);
  49. } else {
  50. _Locale = pContext.getResources().getConfiguration().locale;
  51. }
  52. return _Locale;
  53. }
  54. /**
  55. * 保存用户设置的Locale
  56. * @param pContext Context
  57. * @param pUserLocale Locale
  58. */
  59. public static void saveUserLocale(Context pContext, Locale pUserLocale) {
  60. SharedPreferences _SpLocal=pContext.getSharedPreferences(LOCALE_FILE, Context.MODE_PRIVATE);
  61. SharedPreferences.Editor _Edit=_SpLocal.edit();
  62. String _LocaleJson = localeToJson(pUserLocale);
  63. _Edit.putString(LOCALE_KEY, _LocaleJson);
  64. _Edit.apply();
  65. }
  66. /**
  67. * Locale转成json
  68. * @param pUserLocale UserLocale
  69. * @return json String
  70. */
  71. private static String localeToJson(Locale pUserLocale) {
  72. Gson _Gson = new Gson();
  73. return _Gson.toJson(pUserLocale);
  74. }
  75. /**
  76. * json转成Locale
  77. * @param pLocaleJson LocaleJson
  78. * @return Locale
  79. */
  80. private static Locale jsonToLocale(String pLocaleJson) {
  81. Gson _Gson = new Gson();
  82. return _Gson.fromJson(pLocaleJson, Locale.class);
  83. }
  84. /**
  85. * 更新Locale
  86. * @param pContext Context
  87. * @param pNewUserLocale New User Locale
  88. */
  89. public static void updateLocale(Context pContext, Locale pNewUserLocale) {
  90. if (needUpdateLocale(pContext, pNewUserLocale)) {
  91. Configuration _Configuration = pContext.getResources().getConfiguration();
  92. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
  93. _Configuration.setLocale(pNewUserLocale);
  94. } else {
  95. _Configuration.locale =pNewUserLocale;
  96. }
  97. DisplayMetrics _DisplayMetrics = pContext.getResources().getDisplayMetrics();
  98. pContext.getResources().updateConfiguration(_Configuration, _DisplayMetrics);
  99. saveUserLocale(pContext, pNewUserLocale);
  100. }
  101. }
  102. /**
  103. * 判断需不需要更新
  104. * @param pContext Context
  105. * @param pNewUserLocale New User Locale
  106. * @return true / false
  107. */
  108. public static boolean needUpdateLocale(Context pContext, Locale pNewUserLocale) {
  109. return pNewUserLocale != null && !getCurrentLocale(pContext).equals(pNewUserLocale);
  110. }
  111. }
复制代码

Locale工具类,这里我用SharedPreferences来保存所设置的Locale,Locale是实现了Serializable的。

(四)Activity

  1. package com.ce.switchlanguage;
  2. import android.content.Intent;
  3. import android.os.Bundle;
  4. import android.support.v7.app.AppCompatActivity;
  5. import android.support.v7.widget.Toolbar;
  6. import android.view.Menu;
  7. import android.view.MenuItem;
  8. public class MainActivity extends AppCompatActivity {
  9. @Override
  10. protected void onCreate(Bundle savedInstanceState) {
  11. super.onCreate(savedInstanceState);
  12. setContentView(R.layout.activity_main);
  13. Toolbar _Toolbar =(Toolbar) findViewById(R.id.toolbar);
  14. setSupportActionBar(_Toolbar);
  15. }
  16. @Override
  17. public boolean onCreateOptionsMenu(Menu menu) {
  18. getMenuInflater().inflate(R.menu.main_menu,menu);
  19. return true;
  20. }
  21. @Override
  22. public boolean onOptionsItemSelected(MenuItem item) {
  23. int _ItemId=item.getItemId();
  24. switch (_ItemId) {
  25. case R.id.chinese:
  26. if (LocaleUtils.needUpdateLocale(this, LocaleUtils.LOCALE_CHINESE)) {
  27. LocaleUtils.updateLocale(this, LocaleUtils.LOCALE_CHINESE);
  28. restartAct();
  29. }
  30. break;
  31. case R.id.english:
  32. if (LocaleUtils.needUpdateLocale(this, LocaleUtils.LOCALE_ENGLISH)) {
  33. LocaleUtils.updateLocale(this, LocaleUtils.LOCALE_ENGLISH);
  34. restartAct();
  35. }
  36. break;
  37. case R.id.russian:
  38. if (LocaleUtils.needUpdateLocale(this, LocaleUtils.LOCALE_RUSSIAN)) {
  39. LocaleUtils.updateLocale(this, LocaleUtils.LOCALE_RUSSIAN);
  40. restartAct();
  41. }
  42. }
  43. return true;
  44. }
  45. /**
  46. * 重启当前Activity
  47. */
  48. private void restartAct() {
  49. finish();
  50. Intent _Intent = new Intent(this, MainActivity.class);
  51. startActivity(_Intent);
  52. //清除Activity退出和进入的动画
  53. overridePendingTransition(0, 0);
  54. }
  55. }
复制代码

这里只有一个Activity所以切换的时候重启下当前Activity就好了,栈里还有其他Activity的自己再处理吧。

(五)Application

  1. package com.ce.switchlanguage;
  2. import android.app.Application;
  3. import android.content.res.Configuration;
  4. import android.os.Build;
  5. import java.util.Locale;
  6. public class MyApplication extends Application {
  7. @Override
  8. public void onCreate() {
  9. super.onCreate();
  10. Locale _UserLocale=LocaleUtils.getUserLocale(this);
  11. LocaleUtils.updateLocale(this, _UserLocale);
  12. }
  13. @Override
  14. public void onConfigurationChanged(Configuration newConfig) {
  15. super.onConfigurationChanged(newConfig);
  16. Locale _UserLocale=LocaleUtils.getUserLocale(this);
  17. //系统语言改变了应用保持之前设置的语言
  18. if (_UserLocale != null) {
  19. Locale.setDefault(_UserLocale);
  20. Configuration _Configuration = new Configuration(newConfig);
  21. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
  22. _Configuration.setLocale(_UserLocale);
  23. } else {
  24. _Configuration.locale =_UserLocale;
  25. }
  26. getResources().updateConfiguration(_Configuration, getResources().getDisplayMetrics());
  27. }
  28. }
  29. }
复制代码

在Application onCreate的时候更新下,在系统语言改变的时候也要保持之前设置的语言不变。

源码地址:Android应用内置语言切换

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持程序员之家。



回复

使用道具 举报

关闭

站长推荐上一条 /1 下一条