Android实现应用内置语言切换功能
程序员文章站
2023-12-21 12:19:40
一、需求
有时候应用需要在内部切换语言但又不影响系统的语言,比如是应用现在是中文的,系统语言也是中文的,我把应用的切换成英文显示后系统语言还是中文的,系统语言切换后也...
一、需求
有时候应用需要在内部切换语言但又不影响系统的语言,比如是应用现在是中文的,系统语言也是中文的,我把应用的切换成英文显示后系统语言还是中文的,系统语言切换后也不会被改变,还有就是有些机的系统是被改造精简过的,比如有些国产机的系统的语言就被精简剩中文和英文。支付宝、微信、top story都有在应用内部设置语言切换这样的功能。
二、实现效果
先看看实现效果吧。
三、实现
(一)添加多种语言的资源文件夹及文件
我这默认是英语再添加了个俄文(google翻译的)和中文。
values/strings.xml
<resources> <string name="app_name">switchlanguage</string> <string name="helloworld">hello world!</string> <string name="language">eng</string> <string name="english">english</string> <string name="chinese">中文</string> <string name="russian">русский</string> <string name="secondact">second activity</string> </resources>
values-ru/strings.xml
<resources> <string name="app_name">переключение язык</string> <string name="helloworld">привет мир!</string> <string name="language">русский</string> <string name="secondact">второй активность</string> </resources>
values-zh/strings.xml
<resources> <string name="app_name">切换语言</string> <string name="helloworld">你好 世界!</string> <string name="language">中文</string> <string name="secondact">第二屏</string> </resources>
(二)布局文件
activity_main.xml
默认标题栏的文字是切换语言后是不会被改变的,使用toobar替换掉就可以了。
<?xml version="1.0" encoding="utf-8"?> <linearlayout android:id="@+id/activity_main" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.ce.switchlanguage.mainactivity" xmlns:app="http://schemas.android.com/apk/res-auto"> <android.support.design.widget.appbarlayout android:layout_height="wrap_content" android:layout_width="match_parent" android:theme="@style/apptheme.appbaroverlay"> <android.support.v7.widget.toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionbarsize" android:background="?attr/colorprimary" app:popuptheme="@style/apptheme.popupoverlay" app:title="@string/app_name"/> </android.support.design.widget.appbarlayout> <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/helloworld"/> <button android:id="@+id/change" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="@string/language"/> </linearlayout>
styles.xml
设置语言后需要重启下activity,启动会有个效果,使用windowdisablepreview屏蔽掉它。
<resources> <style name="apptheme" parent="theme.appcompat.light.darkactionbar"> <item name="colorprimary">@color/colorprimary</item> <item name="colorprimarydark">@color/colorprimarydark</item> <item name="coloraccent">@color/coloraccent</item> <item name="windowactionbar">false</item> <item name="windownotitle">true</item> <item name="android:windowdisablepreview">true</item> </style> <style name="apptheme.appbaroverlay" parent="themeoverlay.appcompat.dark.actionbar"/> <style name="apptheme.popupoverlay" parent="themeoverlay.appcompat.dark"/> </resources>
main_menu.xml
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/chinese" android:title="@string/chinese" app:showasaction="never" /> <item android:id="@+id/english" android:title="@string/english" app:showasaction="never" /> <item android:id="@+id/russian" android:title="@string/russian" app:showasaction="never" /> </menu>
(三)localeutils
package com.ce.switchlanguage; import android.content.context; import android.content.sharedpreferences; import android.content.res.configuration; import android.os.build; import android.util.displaymetrics; import com.google.gson.gson; import java.util.locale; public class localeutils { /** * 中文 */ public static final locale locale_chinese = locale.chinese; /** * 英文 */ public static final locale locale_english = locale.english; /** * 俄文 */ public static final locale locale_russian = new locale("ru"); /** * 保存sharedpreferences的文件名 */ private static final string locale_file = "locale_file"; /** * 保存locale的key */ private static final string locale_key = "locale_key"; /** * 获取用户设置的locale * @param pcontext context * @return locale */ public static locale getuserlocale(context pcontext) { sharedpreferences _splocale = pcontext.getsharedpreferences(locale_file, context.mode_private); string _localejson = _splocale.getstring(locale_key, ""); return jsontolocale(_localejson); } /** * 获取当前的locale * @param pcontext context * @return locale */ public static locale getcurrentlocale(context pcontext) { locale _locale; if (build.version.sdk_int >= build.version_codes.n) { //7.0有多语言设置获取顶部的语言 _locale = pcontext.getresources().getconfiguration().getlocales().get(0); } else { _locale = pcontext.getresources().getconfiguration().locale; } return _locale; } /** * 保存用户设置的locale * @param pcontext context * @param puserlocale locale */ public static void saveuserlocale(context pcontext, locale puserlocale) { sharedpreferences _splocal=pcontext.getsharedpreferences(locale_file, context.mode_private); sharedpreferences.editor _edit=_splocal.edit(); string _localejson = localetojson(puserlocale); _edit.putstring(locale_key, _localejson); _edit.apply(); } /** * locale转成json * @param puserlocale userlocale * @return json string */ private static string localetojson(locale puserlocale) { gson _gson = new gson(); return _gson.tojson(puserlocale); } /** * json转成locale * @param plocalejson localejson * @return locale */ private static locale jsontolocale(string plocalejson) { gson _gson = new gson(); return _gson.fromjson(plocalejson, locale.class); } /** * 更新locale * @param pcontext context * @param pnewuserlocale new user locale */ public static void updatelocale(context pcontext, locale pnewuserlocale) { if (needupdatelocale(pcontext, pnewuserlocale)) { configuration _configuration = pcontext.getresources().getconfiguration(); if (build.version.sdk_int >= build.version_codes.jelly_bean_mr1) { _configuration.setlocale(pnewuserlocale); } else { _configuration.locale =pnewuserlocale; } displaymetrics _displaymetrics = pcontext.getresources().getdisplaymetrics(); pcontext.getresources().updateconfiguration(_configuration, _displaymetrics); saveuserlocale(pcontext, pnewuserlocale); } } /** * 判断需不需要更新 * @param pcontext context * @param pnewuserlocale new user locale * @return true / false */ public static boolean needupdatelocale(context pcontext, locale pnewuserlocale) { return pnewuserlocale != null && !getcurrentlocale(pcontext).equals(pnewuserlocale); } }
locale工具类,这里我用sharedpreferences来保存所设置的locale,locale是实现了serializable的。
(四)activity
package com.ce.switchlanguage; import android.content.intent; import android.os.bundle; import android.support.v7.app.appcompatactivity; import android.support.v7.widget.toolbar; import android.view.menu; import android.view.menuitem; public class mainactivity extends appcompatactivity { @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); toolbar _toolbar =(toolbar) findviewbyid(r.id.toolbar); setsupportactionbar(_toolbar); } @override public boolean oncreateoptionsmenu(menu menu) { getmenuinflater().inflate(r.menu.main_menu,menu); return true; } @override public boolean onoptionsitemselected(menuitem item) { int _itemid=item.getitemid(); switch (_itemid) { case r.id.chinese: if (localeutils.needupdatelocale(this, localeutils.locale_chinese)) { localeutils.updatelocale(this, localeutils.locale_chinese); restartact(); } break; case r.id.english: if (localeutils.needupdatelocale(this, localeutils.locale_english)) { localeutils.updatelocale(this, localeutils.locale_english); restartact(); } break; case r.id.russian: if (localeutils.needupdatelocale(this, localeutils.locale_russian)) { localeutils.updatelocale(this, localeutils.locale_russian); restartact(); } } return true; } /** * 重启当前activity */ private void restartact() { finish(); intent _intent = new intent(this, mainactivity.class); startactivity(_intent); //清除activity退出和进入的动画 overridependingtransition(0, 0); } }
这里只有一个activity所以切换的时候重启下当前activity就好了,栈里还有其他activity的自己再处理吧。
(五)application
package com.ce.switchlanguage; import android.app.application; import android.content.res.configuration; import android.os.build; import java.util.locale; public class myapplication extends application { @override public void oncreate() { super.oncreate(); locale _userlocale=localeutils.getuserlocale(this); localeutils.updatelocale(this, _userlocale); } @override public void onconfigurationchanged(configuration newconfig) { super.onconfigurationchanged(newconfig); locale _userlocale=localeutils.getuserlocale(this); //系统语言改变了应用保持之前设置的语言 if (_userlocale != null) { locale.setdefault(_userlocale); configuration _configuration = new configuration(newconfig); if (build.version.sdk_int >= build.version_codes.jelly_bean_mr1) { _configuration.setlocale(_userlocale); } else { _configuration.locale =_userlocale; } getresources().updateconfiguration(_configuration, getresources().getdisplaymetrics()); } } }
在application oncreate的时候更新下,在系统语言改变的时候也要保持之前设置的语言不变。
源码地址:android应用内置语言切换
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。