android程序内多语言切换不需要重新启动的解决方案

本文主要是介绍android程序内多语言切换不需要重新启动的解决方案,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

关于android程序内的的多语言切换,一般能搜索到这段代码:

    public void switchLanguage(Locale locale) {Configuration config = getResources().getConfiguration();// 获得设置对象Resources resources = getResources();// 获得res资源对象DisplayMetrics dm = resources.getDisplayMetrics();// 获得屏幕参数:主要是分辨率,像素等。config.locale = locale; //语言resources.updateConfiguration(config, dm);}

多数给出的方案是重新启动activity或者重新setContentView,但是微信却能办到不重启又能修改语言,怎么办到的呢?就让鄙人吹吹实现思路吧:首先定义一个多语言切换支持的自定义控件,整个app涉及到多语言的布局的地方都要使用它,控件初始化的时候获取string资源id,保存string资源id,settext的时候要更新string资源id,切换语言的时候用上文所提供的代码,设置完语言后(假设设置成中文),如果重新通过string资源id设置text,那么就会显示中文文字,如果我们不主动去更新,他们就不自觉了,就像泡妹子一样,主动才能到手,所以我们需要对所有的多语言支持的自定义控件进行更新,方法就是通过发送
消息给每一个activity,activity收到后,拿出自己的view,把全部子view列举一次,如果是多语言支持的自定义控件,就更新它,详细步骤看下文:

步骤1:

建立多语言文件夹,并写好多语言所需的文字

values-zh

values-en

…..

不细讲了

步骤2:

定义多语言切换接口,需要自定义view实现它

在控件包(widget包)下建立AppTextView和AppButton

建立接口:LanguageView,包含以下方法:

    //由于setText无法被重写,需要添加以下三个必要的方法,如果你的app不需要对多语言的textview修改值(只是xml写死就够了),那就不需要实现他们void setTextById (@StringRes int id);//手动设置textIdvoid setTextWithString (String text);//手动去掉textId,不然重新加载语言的时候会被重置掉void setTextByArrayAndIndex (@ArrayRes int arrId, @StringRes int arrIndex);//手动通过TextArray设置语言void reLoadLanguage();//修改语言时主要调用的方法

步骤3:

自定义多语言切换view:

public class AppTextView extends TextView implements LanguageView {private int textId ;//文字idprivate int hintId ;//hint的idprivate int arrResId,arrResIndex;public AppTextView(Context context) {super(context);init(context, null);}public AppTextView(Context paramContext, AttributeSet paramAttributeSet) {super(paramContext, paramAttributeSet);init(paramContext, paramAttributeSet);}public AppTextView(Context paramContext, AttributeSet paramAttributeSet, int paramInt) {super(paramContext, paramAttributeSet, paramInt);init(paramContext, paramAttributeSet);}/*** 初始化获取xml的资源id* @param context* @param attributeSet*/private void init (Context context,AttributeSet attributeSet) {if (attributeSet!=null) {String textValue = attributeSet.getAttributeValue(ANDROIDXML, "text");if (!(textValue==null || textValue.length()<2)) {//如果是 android:text="@string/testText"//textValue会长这样 @156878785,去掉@号就是资源idtextId = StringUtil.string2int(textValue.substring(1,textValue.length()));}String hintValue = attributeSet.getAttributeValue(ANDROIDXML, "hint");if (!(hintValue==null || hintValue.length()<2)) {hintId = StringUtil.string2int(hintValue.substring(1,hintValue.length()));}}}@Overridepublic void setTextById (@StringRes int strId) {this.textId = strId;setText(strId);}@Overridepublic void setTextWithString(String text) {this.textId = 0;setText(text);}@Overridepublic void setTextByArrayAndIndex (@ArrayRes int arrId, @StringRes int arrIndex) {arrResId = arrId;arrResIndex = arrIndex;String[] strs = getContext().getResources().getStringArray(arrId);setText(strs[arrIndex]);}@Overridepublic void reLoadLanguage () {try {if (textId>0) {setText(textId);} else if (arrResId>0) {String[] strs = getContext().getResources().getStringArray(arrResId);setText(strs[arrResIndex]);}if (hintId>0) {setHint(hintId);}} catch (Exception e) {e.printStackTrace();}}
}

步骤4:

博客出处
编写xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical" android:layout_width="match_parent"android:layout_height="match_parent"><cn.georgeyang.languageupdate.widget.AppTextView
        android:text="@string/testText"android:layout_width="wrap_content"android:layout_height="wrap_content" /><cn.georgeyang.languageupdate.widget.AppButton
        android:id="@+id/btn"android:text="@string/next"android:layout_width="wrap_content"android:layout_height="wrap_content" /></LinearLayout>

步骤5:

写好activity代码后,添加eventbus,实现activity之间的通信(用其它方式实现通信也行)

gradle添加    compile 'org.greenrobot:eventbus:3.0.0'public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);EventBus.getDefault().register(this);findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {switchLanguage(Locale.CHINESE);ClassEvent event = new ClassEvent();event.msg = "do it";EventBus.getDefault().post(event);}});}public void switchLanguage(Locale locale) {Configuration config = getResources().getConfiguration();// 获得设置对象Resources resources = getResources();// 获得res资源对象DisplayMetrics dm = resources.getDisplayMetrics();// 获得屏幕参数:主要是分辨率,像素等。config.locale = locale; resources.updateConfiguration(config, dm);}@Subscribe(threadMode = ThreadMode.MAIN) //在ui线程执行public void onStringEvent(ClassEvent event) {Log.d("test","MainActivity got message:" +  event);//start update language}@Overrideprotected void onDestroy(){super.onDestroy();EventBus.getDefault().unregister(this);//反注册EventBus}
}

步骤6

编写修改多语言文字的代码:

    //给给出一个view,把子view全部检查一遍,如果是实现LanguageView接口的view,更新语言public static void updateViewLanguage(View view) {if (view instanceof ViewGroup) {ViewGroup vg = (ViewGroup) view;int count = vg.getChildCount();for (int i = 0; i < count; i++) {updateViewLanguage(vg.getChildAt(i));}} else if (view instanceof LanguageView) {LanguageView tv = (LanguageView) view;tv.reLoadLanguage();}}

修改多语言文字的代码写好后,开始调用:

    @Subscribe(threadMode = ThreadMode.MAIN) //在ui线程执行public void onStringEvent(ClassEvent event) {Log.d("test","MainActivity got message:" +  event);ViewUtil.updateViewLanguage(findViewById(android.R.id.content));}

最后点一下按钮就能更新语言了,activity没有重启,而且上一个activity的语言也跟着改变,不需要自己找出textview手动修改,是不是很方便呢?!

最后给出demo代码:

gitDemo

这篇关于android程序内多语言切换不需要重新启动的解决方案的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/994042

相关文章

C++高效内存池实现减少动态分配开销的解决方案

《C++高效内存池实现减少动态分配开销的解决方案》C++动态内存分配存在系统调用开销、碎片化和锁竞争等性能问题,内存池通过预分配、分块管理和缓存复用解决这些问题,下面就来了解一下... 目录一、C++内存分配的性能挑战二、内存池技术的核心原理三、主流内存池实现:TCMalloc与Jemalloc1. TCM

MyBatis Plus 中 update_time 字段自动填充失效的原因分析及解决方案(最新整理)

《MyBatisPlus中update_time字段自动填充失效的原因分析及解决方案(最新整理)》在使用MyBatisPlus时,通常我们会在数据库表中设置create_time和update... 目录前言一、问题现象二、原因分析三、总结:常见原因与解决方法对照表四、推荐写法前言在使用 MyBATis

Go语言中泄漏缓冲区的问题解决

《Go语言中泄漏缓冲区的问题解决》缓冲区是一种常见的数据结构,常被用于在不同的并发单元之间传递数据,然而,若缓冲区使用不当,就可能引发泄漏缓冲区问题,本文就来介绍一下问题的解决,感兴趣的可以了解一下... 目录引言泄漏缓冲区的基本概念代码示例:泄漏缓冲区的产生项目场景:Web 服务器中的请求缓冲场景描述代码

Go语言如何判断两张图片的相似度

《Go语言如何判断两张图片的相似度》这篇文章主要为大家详细介绍了Go语言如何中实现判断两张图片的相似度的两种方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 在介绍技术细节前,我们先来看看图片对比在哪些场景下可以用得到:图片去重:自动删除重复图片,为存储空间"瘦身"。想象你是一个

Java死锁问题解决方案及示例详解

《Java死锁问题解决方案及示例详解》死锁是指两个或多个线程因争夺资源而相互等待,导致所有线程都无法继续执行的一种状态,本文给大家详细介绍了Java死锁问题解决方案详解及实践样例,需要的朋友可以参考下... 目录1、简述死锁的四个必要条件:2、死锁示例代码3、如何检测死锁?3.1 使用 jstack3.2

Go语言中Recover机制的使用

《Go语言中Recover机制的使用》Go语言的recover机制通过defer函数捕获panic,实现异常恢复与程序稳定性,具有一定的参考价值,感兴趣的可以了解一下... 目录引言Recover 的基本概念基本代码示例简单的 Recover 示例嵌套函数中的 Recover项目场景中的应用Web 服务器中

html 滚动条滚动过快会留下边框线的解决方案

《html滚动条滚动过快会留下边框线的解决方案》:本文主要介绍了html滚动条滚动过快会留下边框线的解决方案,解决方法很简单,详细内容请阅读本文,希望能对你有所帮助... 滚动条滚动过快时,会留下边框线但其实大部分时候是这样的,没有多出边框线的滚动条滚动过快时留下边框线的问题通常与滚动条样式和滚动行

Oracle修改端口号之后无法启动的解决方案

《Oracle修改端口号之后无法启动的解决方案》Oracle数据库更改端口后出现监听器无法启动的问题确实较为常见,但并非必然发生,这一问题通常源于​​配置错误或环境冲突​​,而非端口修改本身,以下是系... 目录一、问题根源分析​​​二、保姆级解决方案​​​​步骤1:修正监听器配置文件 (listener.

MySQL版本问题导致项目无法启动问题的解决方案

《MySQL版本问题导致项目无法启动问题的解决方案》本文记录了一次因MySQL版本不一致导致项目启动失败的经历,详细解析了连接错误的原因,并提供了两种解决方案:调整连接字符串禁用SSL或统一MySQL... 目录本地项目启动报错报错原因:解决方案第一个:第二种:容器启动mysql的坑两种修改时区的方法:本地

安装centos8设置基础软件仓库时出错的解决方案

《安装centos8设置基础软件仓库时出错的解决方案》:本文主要介绍安装centos8设置基础软件仓库时出错的解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录安装Centos8设置基础软件仓库时出错版本 8版本 8.2.200android4版本 javas