目录

一、简介

二、效果预览

三、实现步骤

1、功能实现

2、配置多语言文件

四、MultiLanguageUtils分析

五、Demo地址

六、内容推荐


一、简介

我想搜到这篇文章的朋友应该不需要我多介绍,也明白多语言是用来干嘛。。。

当一个应用越做越大之后,用的人越来越多,要满足不同的群体所以都会有这一功能。

不过你会发现越到后面添加这功能会比较麻烦。所以前期做好准备为佳。

不扯这乱七八糟的东西了。。。。亮剑吧!!!

二、效果预览

是不是要先看看大招是咋样的,万一是花拳绣腿。不满意,就浪费大家时间了。

大家可可能会奇怪,不是切换成英文了吗?  怎么还有中文字体。

其实我只是对首页的 标题底部导航栏  做了处理 其他的没有变

所以大家看效果的话 只需观察 那两处地方即可。

如果对这个功能有兴趣可以继续往下观察。。没兴趣的也请往下看 ,看完可能会更没兴趣。哈哈 开个玩笑

三、实现步骤

1、功能实现

布局我就不解释了,就随便搭搭。源码地址就贴在最下面,想copy的同学自己去下载哈。对了,如果不错。别忘了 Star

主要的功能就在于当我选中某个语言时,点击保存(上图是“打钩”的图片)的时候去实现语言的切换。 那么,是怎么实现的呢?预知后事如何且看下文分解!!

上菜:点击保存执行事假

     //区分是选中哪种语言switch (datas.get(checkPos)) {case "跟随系统"://切换到 跟随系统//获取手机系统语言Locale locale = MultiLanguageUtils.getSystemLanguage().get(0);String language = locale.getLanguage();String country = locale.getCountry();//切换成手机系统语言  例:手机系统是中文则换成中文MultiLanguageUtils.changeLanguage(activity,language, country);//清空SP数据 ,用于当系统切换语言时 应用可以同步保持切换 例:系统转换成英文 则应用语言也会变成英文MultiLanguageUtils.changeLanguage(activity,null,null);break;case "简体中文":// 切换到 中文MultiLanguageUtils.changeLanguage(activity, "zh", "ZH");break;case "English"://切换到 英文MultiLanguageUtils.changeLanguage(activity, "en", "US");break;default://默认切换成中文MultiLanguageUtils.changeLanguage(activity, "zh", "ZH");break;}//关闭应用所有Activity//AppManager.getAppManager().finishAllActivity();//启动 MainActivity//IntentUtils.toActivity(activity, MainActivity.class,true);

上面的切换语言功能都已经封装成一个工具类,当需要执行切换语言的时候 只需调用一行代码即可。是不是很兴奋 ,其实更麻烦的在后面,先安慰一下大家。

要让切换语言起效果,还需要重启APP。

例:上面代码是先调用了个人封装的一个Activity管理类来关闭所有的页面,然后再重启MainActivity。大家可以根据情况自己写,也可以到源码地址找到相关工具类拿去用。

大餐来了 MultiLanguageUtils.class  先感谢下大神提供的这个类:https://blog.csdn.net/m0_38074457/article/details/84993366

个人做了调整,改的有点面目全非,现在分享给大家。如果还行。。。你们懂得 点个赞意思一下就行 ,,关注,分享,打赏 我是不敢想的。

import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.os.Bundle;
import android.os.LocaleList;
import android.support.v4.os.ConfigurationCompat;
import android.support.v4.os.LocaleListCompat;
import android.text.TextUtils;
import android.util.DisplayMetrics;import java.util.Locale;import blcs.lwb.lwbtool.Constants;/*** Todo 多语言设置* 来自:https://blog.csdn.net/m0_38074457/article/details/84993366* 使用步骤:* 1、Application中onCreate添加registerActivityLifecycleCallbacks(MultiLanguageUtils.callbacks);@Overrideprotected void attachBaseContext(Context base) {//系统语言等设置发生改变时会调用此方法,需要要重置app语言super.attachBaseContext(MultiLanguageUtils.attachBaseContext(base));}* 2、改变应用语言调用MultiLanguageUtils.changeLanguage(activity,type,type);*/
//public final static String SP_LANGUAGE="SP_LANGUAGE";
//public final static String SP_COUNTRY="SP_COUNTRY";
public class MultiLanguageUtils {/*** TODO 1、 修改应用内语言设置* @param language    语言  zh/en* @param area      地区*/public static void changeLanguage(Context context,String language, String area) {if (TextUtils.isEmpty(language) && TextUtils.isEmpty(area)) {//如果语言和地区都是空,那么跟随系统sSPUtils.put(context, Constants.SP_LANGUAGE,"");SPUtils.put(context, Constants.SP_COUNTRY,"");} else {//不为空,那么修改app语言,并true是把语言信息保存到sp中,false是不保存到sp中Locale newLocale = new Locale(language, area);setAppLanguage(context,newLocale);saveLanguageSetting(context, newLocale);}}/*** Todo 更新应用语言* @param context* @param locale*/private static void setAppLanguage(Context context, Locale locale) {Resources resources = context.getResources();DisplayMetrics metrics = resources.getDisplayMetrics();Configuration configuration = resources.getConfiguration();if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {configuration.setLocale(locale);configuration.setLocales(new LocaleList(locale));context.createConfigurationContext(configuration);} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {configuration.setLocale(locale);resources.updateConfiguration(configuration,metrics);} else {configuration.locale = locale;resources.updateConfiguration(configuration,metrics);}}/*** TODO 3、 跟随系统语言*/public static Context attachBaseContext(Context context) {String spLanguage = (String) SPUtils.get(context, Constants.SP_LANGUAGE,"");String spCountry = (String) SPUtils.get(context, Constants.SP_COUNTRY,"");if(!TextUtils.isEmpty(spLanguage)&&!TextUtils.isEmpty(spCountry)){Locale  locale = new Locale(spLanguage, spCountry);setAppLanguage(context, locale);}return context;}/*** 判断sp中和app中的多语言信息是否相同*/public static boolean isSameWithSetting(Context context) {Locale locale = getAppLocale(context);String language = locale.getLanguage();String country = locale.getCountry();String sp_language = (String) SPUtils.get(context, Constants.SP_LANGUAGE,"");String sp_country = (String) SPUtils.get(context, Constants.SP_COUNTRY,"");if (language.equals(sp_language) && country.equals(sp_country)) {return true;} else {return false;}}/*** 保存多语言信息到sp中*/public static void saveLanguageSetting(Context context, Locale locale) {SPUtils.put(context, Constants.SP_LANGUAGE,locale.getLanguage());SPUtils.put(context, Constants.SP_COUNTRY,locale.getCountry());}/*** 获取应用语言*/public static Locale getAppLocale(Context context){Locale local;if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {local =context.getResources().getConfiguration().getLocales().get(0);} else {local =context.getResources().getConfiguration().locale;}return local;}/*** 获取系统语言*/public static LocaleListCompat getSystemLanguage(){Configuration configuration = Resources.getSystem().getConfiguration();LocaleListCompat locales = ConfigurationCompat.getLocales(configuration);return locales;}//注册Activity生命周期监听回调,此部分一定加上,因为有些版本不加的话多语言切换不回来//registerActivityLifecycleCallbacks(callbacks);public static  Application.ActivityLifecycleCallbacks callbacks = new Application.ActivityLifecycleCallbacks() {@Overridepublic void onActivityCreated(Activity activity, Bundle savedInstanceState) {String language = (String) SPUtils.get(activity, Constants.SP_LANGUAGE,"");String country = (String) SPUtils.get(activity, Constants.SP_COUNTRY,"");LogUtils.e(language);if (!TextUtils.isEmpty(language) && !TextUtils.isEmpty(country)) {//强制修改应用语言if (!isSameWithSetting(activity)) {Locale locale = new Locale(language, country);setAppLanguage(activity,locale);}}}@Overridepublic void onActivityStarted(Activity activity) {}@Overridepublic void onActivityResumed(Activity activity) {}@Overridepublic void onActivityPaused(Activity activity) {}@Overridepublic void onActivityStopped(Activity activity) {}@Overridepublic void onActivitySaveInstanceState(Activity activity, Bundle outState) {}@Overridepublic void onActivityDestroyed(Activity activity) {}};}

这里可以能还需要一个封装的SP工具

import android.content.Context;
import android.content.SharedPreferences;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
/*** SharedPreferences的封装*/
public class SPUtils
{public SPUtils(){/* cannot be instantiated */throw new UnsupportedOperationException("cannot be instantiated");}/*** 保存在手机里面的文件名*/public static final String FILE_NAME = "share_data";/*** 保存数据的方法,我们需要拿到保存数据的具体类型,然后根据类型调用不同的保存方法** @param context* @param key* @param object*/public static void put(Context context, String key, Object object){SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);SharedPreferences.Editor editor = sp.edit();if (object instanceof String){editor.putString(key, (String) object);}else if (object instanceof Integer){editor.putInt(key, (Integer) object);}else if (object instanceof Boolean){editor.putBoolean(key, (Boolean) object);}else if (object instanceof Float){editor.putFloat(key, (Float) object);}else if (object instanceof Long){editor.putLong(key, (Long) object);}else{editor.putString(key, object.toString());}SharedPreferencesCompat.apply(editor);}/*** 得到保存数据的方法,我们根据默认值得到保存的数据的具体类型,然后调用相对于的方法获取值** @param context* @param key* @param defaultObject* @return*/public static Object get(Context context, String key, Object defaultObject){SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);if (defaultObject instanceof String){return sp.getString(key, (String) defaultObject);}else if (defaultObject instanceof Integer){return sp.getInt(key, (Integer) defaultObject);}else if (defaultObject instanceof Boolean){return sp.getBoolean(key, (Boolean) defaultObject);}else if (defaultObject instanceof Float){return sp.getFloat(key, (Float) defaultObject);}else if (defaultObject instanceof Long){return sp.getLong(key, (Long) defaultObject);}return null;}/*** 移除某个key值已经对应的值** @param context* @param key*/public static void remove(Context context, String key){SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);SharedPreferences.Editor editor = sp.edit();editor.remove(key);SharedPreferencesCompat.apply(editor);}/*** 清除所有数据** @param context*/public static void clear(Context context){SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);SharedPreferences.Editor editor = sp.edit();editor.clear();SharedPreferencesCompat.apply(editor);}/*** 查询某个key是否已经存在** @param context* @param key* @return*/public static boolean contains(Context context, String key){SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);return sp.contains(key);}/*** 返回所有的键值对** @param context* @return*/public static Map<String, ?> getAll(Context context){SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);return sp.getAll();}/*** 创建一个解决SharedPreferencesCompat.apply方法的一个兼容类* @author zhy**/private static class SharedPreferencesCompat{private static final Method sApplyMethod = findApplyMethod();/*** 反射查找apply的方法* @return*/@SuppressWarnings({ "unchecked", "rawtypes" })private static Method findApplyMethod(){try{Class clz = SharedPreferences.Editor.class;return clz.getMethod("apply");} catch (NoSuchMethodException e){}return null;}/*** 如果找到则使用apply执行,否则使用commit** @param editor*/public static void apply(SharedPreferences.Editor editor){try{if (sApplyMethod != null){sApplyMethod.invoke(editor);return;}} catch (IllegalArgumentException e){} catch (IllegalAccessException e){} catch (InvocationTargetException e){}editor.commit();}}
}

如果你们以为有了这几个工具就可以出去吹牛逼,那么是你们天真了,而不是我想的太多。还有更麻烦的事情还没开始呢

在继承Application的类中onCreate方法内添加监听回调

 @Overridepublic void onCreate() {super.onCreate();//多语言设置registerActivityLifecycleCallbacks(MultiLanguageUtils.callbacks);
}

跟随系统语言也要在Application中的attachBaseContext配置(感觉可以去掉,本人亲测根本没有调用到。不知道是不是不同机型的原因。先保留着 ,后续若发现无用,可删掉。写出来主要是钱作者有写但描述不够详细)

    @Overrideprotected void attachBaseContext(Context base) {//系统语言等设置发生改变时会调用此方法,需要要重置app语言super.attachBaseContext(MultiLanguageUtils.attachBaseContext(base));}

2、配置多语言文件

最麻烦的工作来了,若前期没做好相关工作。那么你可以开始跟我一步步来实现了

1、新增多语言文件

可以手动创建,但要符合命名规范。(不推荐)

这里介绍androidStudio 新建多语言文本方法

右击res——New——Android resource file

创建完文件后。。。剩下就是抽出文本进行翻译了。。

2、把项目中的文本都写到strings.xml文件中

像我这样:

如何使用这些文本?

UI中: android:text="@string/Title"

代码中:context.getString(R.string.Title)

快捷键使用:选中文本使用  Alt + Enter     打开Extract string resource

给文本命名  ——> 打钩所有的values——>点击OK  就可以自动生成到strings文件里面

接着翻译 values-en 文件中的文本。

到这里差不多都介绍完了 ,若有代码遗落可查看源码 。毕竟已经实现过了 ,拿出来分析给大家,可能会有疏忽。

MultiLanguageUtils只加了简单注释,若对MultiLanguageUtils有什么不理解的地方 请继续往下看。

四、MultiLanguageUtils分析

我们切换语言只需调用:MultiLanguageUtils.changeLanguage(activity, "zh", "ZH");

1、changeLanguage(Context context,String language, String area):

 public static void changeLanguage(Context context,String language, String area) {if (TextUtils.isEmpty(language) && TextUtils.isEmpty(area)) {//如果语言和地区都是空,那么跟随系统sSPUtils.put(context, Constants.SP_LANGUAGE,"");SPUtils.put(context, Constants.SP_COUNTRY,"");} else {//不为空,那么修改app语言,并true是把语言信息保存到sp中,false是不保存到sp中Locale newLocale = new Locale(language, area);setAppLanguage(context,newLocale);saveLanguageSetting(context, newLocale);}}

首先判断language,area 是否为空

空:清空app本地存储多语言的sp,为什么要清空呢?

当启动APP时会回调 registerActivityLifecycleCallbacks(MultiLanguageUtils.callbacks);

该方法内部会绑定生命周期调用如下方法

        @Overridepublic void onActivityCreated(Activity activity, Bundle savedInstanceState) {String language = (String) SPUtils.get(activity, Constants.SP_LANGUAGE,"");String country = (String) SPUtils.get(activity, Constants.SP_COUNTRY,"");LogUtils.e(language);if (!TextUtils.isEmpty(language) && !TextUtils.isEmpty(country)) {//强制修改应用语言if (!isSameWithSetting(activity)) {Locale locale = new Locale(language, country);setAppLanguage(activity,locale);}}}

若sp有值则根据对应的值设置APP语言 ,若为空 ,则会默认取系统语言。

注:当选中“跟随系统语言”时,若不清空SP。则会造成当系统语言改变,App还是会根据SP的值来设置语言。

有值:根据传入的language,area 值切换成相对应的语言

2、setAppLanguage(Context context, Locale locale)

/*** Todo 更新应用语言* @param context* @param locale*/private static void setAppLanguage(Context context, Locale locale) {Resources resources = context.getResources();DisplayMetrics metrics = resources.getDisplayMetrics();Configuration configuration = resources.getConfiguration();if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {configuration.setLocale(locale);configuration.setLocales(new LocaleList(locale));context.createConfigurationContext(configuration);} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {configuration.setLocale(locale);resources.updateConfiguration(configuration,metrics);} else {configuration.locale = locale;resources.updateConfiguration(configuration,metrics);}}

更改应用的语言主要还是通过更改App配置来实现,主要实现步骤如下:

1、先获取资源配置对象 2、更改资源对象属性 3、更新配置信息

多语言语言适配了Android N  (7.0)

7.0以前更新配置信息使用

resources.updateConfiguration(configuration, metrics);

7.0以后更新配置信息使用

context.createConfigurationContext(configuration);

3、跟随系统语言实现思路分析

1、当保存跟随系统语言时,获取系统语言 ,并更新App语言。

2、当更改手机设置语言后,启动App的时候重新更改App语言(保存其它语言信息的时候,启动App是时候也需要根据保存信息重新设置)

这里主要分析第二点。第一点只要调用changeAppLanguage 就行了

当App启动的时候会回调registerActivityLifecycleCallbacks(MultiLanguageUtils.callbacks);

        @Overridepublic void onActivityCreated(Activity activity, Bundle savedInstanceState) {String language = (String) SPUtils.get(activity, Constants.SP_LANGUAGE,"");String country = (String) SPUtils.get(activity, Constants.SP_COUNTRY,"");LogUtils.e(language);if (!TextUtils.isEmpty(language) && !TextUtils.isEmpty(country)) {//强制修改应用语言if (!isSameWithSetting(activity)) {Locale locale = new Locale(language, country);setLanguage(activity,locale);}}}

也是通过Sp是否有保存信息来设置系统语言。

终于写完了,看了一下篇幅还是挺长,容我感慨一下。又熬夜了 ,大家要手下留

好吧!!! 再见

五、Demo地址

https://github.com/DayorNight/BLCS

六、内容推荐

简书:https://www.jianshu.com/p/0f957ead4fa0

《Android 仿微信全局字体大小调整》

《Android JUnit单元测试》

《Android Log日志封装》

《Android Rxjava+Retrofit网络请求框架封装(一)》

如果你觉得我写的不错或者对您有所帮助的话

不妨顶一个【微笑】,别忘了点赞、收藏、加关注哈

看在我花了这么多时间整理写成文章分享给大家的份上,记得手下留情哈

您的每个举动都是对我莫大的支持

Android 仿微信多语言切换相关推荐

  1. Android仿微信聊天语言点击喇叭动画效果

    微信聊天界面点击语音时,喇叭的动画效果,下面上代码,该类是控制背景变化的工具类,不涉及语音录制和播放. 图片资源: package xxx;import android.os.Handler; imp ...

  2. android 表情键盘切换,Android仿微信键盘切换效果

    Android 仿微信的键盘切换(录音,表情,文字,其他),IM通讯,类似朋友圈只要涉及到文字等相关的app都会要涉及到键盘的处理,今天就给大家分享一下Android 仿微信的键盘切换. 效果图如下: ...

  3. php仿微信底部菜单,Android实现简单底部导航栏 Android仿微信滑动切换效果

    Android仿微信滑动切换最终实现效果: 大体思路: 1. 主要使用两个自定义View配合实现; 底部图标加文字为一个自定义view,底部导航栏为一个载体,根据需要来添加底部图标; 2. 底部导航栏 ...

  4. android仿微信的activity平滑水平切换动画,Android实现简单底部导航栏 Android仿微信滑动切换效果...

    Android实现简单底部导航栏 Android仿微信滑动切换效果 发布时间:2020-10-09 19:48:00 来源:脚本之家 阅读:96 作者:丶白泽 Android仿微信滑动切换最终实现效果 ...

  5. android滑动菜单图标,Android实现简单底部导航栏 Android仿微信滑动切换效果

    Android仿微信滑动切换最终实现效果: 大体思路: 1. 主要使用两个自定义View配合实现; 底部图标加文字为一个自定义view,底部导航栏为一个载体,根据需要来添加底部图标; 2. 底部导航栏 ...

  6. android 底部滑动效果怎么做,Android实现简单底部导航栏 Android仿微信滑动切换效果...

    android仿微信滑动切换最终实现效果: 大体思路: 1. 主要使用两个自定义view配合实现; 底部图标加文字为一个自定义view,底部导航栏为一个载体,根据需要来添加底部图标; 2. 底部导航栏 ...

  7. Android app应用多语言切换功能实现

    最近在做一个多语言切换的功能,类似于微信的语言切换,搜了下资料基本上都是以下这种: 1. 实现的效果 和微信类似,在设置界面打开切换语言的界面,选择语言后重启 HomeActivity,语言切换完成, ...

  8. android右滑返回动画,Android仿微信右滑返回功能的实例代码

    先上效果图,如下: 先分析一下功能的主要技术点,右滑即手势判断,当滑到一直距离时才执行返回,并且手指按下的位置是在屏幕的最左边(这个也是有一定范围的),  这些可以实现onTouchEvent来实现. ...

  9. Android 仿微信语音录音小控件

    Android 仿微信语音录音小控件 前段时间一直在做IM聊天这方面的撸码工作,涉及到了很多小控件,有时间我会慢慢给大家分享一下我的小成果,希望大家一起学习,一起进步,今天来和大家来说一下Androi ...

最新文章

  1. oracle数据库配置失败,oracle11g – Oracle 11G XE安装错误:数据库配置失败
  2. 遇到奇怪的C#/C/C++或者Java的bug可以去问问Coverity
  3. spring 初始化数据库
  4. Hadoop集群安装-CDH5(5台服务器集群)
  5. 分段路由中的控制指的什么?—Vecloud
  6. 在TCP客户端连接成功的回调函数里,无法访问到客户端套接字的明细
  7. matlab数字信号处理实验报告,Matlab数字信号处理实验报告.pdf
  8. 用Python绘制了若干张词云图,惊艳了所有人
  9. 自用plsql破解方法
  10. 微信小程序 java社区团购系统springboot
  11. 程序员实用小工具(一)
  12. 简单的学生选课系统——基于Servlet+Ajax
  13. 27个精美的时间线(含源代码)
  14. 2021年WordPress博客装修美化(一)
  15. 矩阵论(零):线性代数基础知识整理(1)——逆矩阵、(广义)初等变换、满秩分解
  16. Date的after和before方法
  17. excel智能提取_Excel智能艺术家谱
  18. CSDN是什么???
  19. 《卸甲笔记》-基础语法对比
  20. 啤酒和尿不湿?购物篮分析、商品关联分析和关联规则算法都给你搞清楚(上—理论篇)

热门文章

  1. STM32CubeMX学习--ThreadX_UART
  2. Windows Azure Platform (三)云计算的特点
  3. Python 日期处理
  4. foxmail和outlook2007邮件如何互相导入?
  5. MySQL存储引擎概叙
  6. c语言cache,高速C/C++编译工具ccache
  7. 1000元计算机配置方案,1000元赛扬J345低功耗主机推荐 2018最便宜电脑配置方案 (全文)...
  8. android仿微信充值布局,仿微信充值金额输入框-自定义EditText
  9. UVM--TLM2.0通信
  10. 十万个为什么 —— 古代没有拼音,怎么认字?