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

相关文章

Spring Security常见问题及解决方案

《SpringSecurity常见问题及解决方案》SpringSecurity是Spring生态的安全框架,提供认证、授权及攻击防护,支持JWT、OAuth2集成,适用于保护Spring应用,需配置... 目录Spring Security 简介Spring Security 核心概念1. ​Securit

MySQL逻辑删除与唯一索引冲突解决方案

《MySQL逻辑删除与唯一索引冲突解决方案》本文探讨MySQL逻辑删除与唯一索引冲突问题,提出四种解决方案:复合索引+时间戳、修改唯一字段、历史表、业务层校验,推荐方案1和方案3,适用于不同场景,感兴... 目录问题背景问题复现解决方案解决方案1.复合唯一索引 + 时间戳删除字段解决方案2:删除后修改唯一字

golang程序打包成脚本部署到Linux系统方式

《golang程序打包成脚本部署到Linux系统方式》Golang程序通过本地编译(设置GOOS为linux生成无后缀二进制文件),上传至Linux服务器后赋权执行,使用nohup命令实现后台运行,完... 目录本地编译golang程序上传Golang二进制文件到linux服务器总结本地编译Golang程序

深入理解Go语言中二维切片的使用

《深入理解Go语言中二维切片的使用》本文深入讲解了Go语言中二维切片的概念与应用,用于表示矩阵、表格等二维数据结构,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧... 目录引言二维切片的基本概念定义创建二维切片二维切片的操作访问元素修改元素遍历二维切片二维切片的动态调整追加行动态

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

Android ClassLoader加载机制详解

《AndroidClassLoader加载机制详解》Android的ClassLoader负责加载.dex文件,基于双亲委派模型,支持热修复和插件化,需注意类冲突、内存泄漏和兼容性问题,本文给大家介... 目录一、ClassLoader概述1.1 类加载的基本概念1.2 android与Java Class

使用Docker构建Python Flask程序的详细教程

《使用Docker构建PythonFlask程序的详细教程》在当今的软件开发领域,容器化技术正变得越来越流行,而Docker无疑是其中的佼佼者,本文我们就来聊聊如何使用Docker构建一个简单的Py... 目录引言一、准备工作二、创建 Flask 应用程序三、创建 dockerfile四、构建 Docker

Go语言中make和new的区别及说明

《Go语言中make和new的区别及说明》:本文主要介绍Go语言中make和new的区别及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1 概述2 new 函数2.1 功能2.2 语法2.3 初始化案例3 make 函数3.1 功能3.2 语法3.3 初始化

IDEA中新建/切换Git分支的实现步骤

《IDEA中新建/切换Git分支的实现步骤》本文主要介绍了IDEA中新建/切换Git分支的实现步骤,通过菜单创建新分支并选择是否切换,创建后在Git详情或右键Checkout中切换分支,感兴趣的可以了... 前提:项目已被Git托管1、点击上方栏Git->NewBrancjsh...2、输入新的分支的

Java 线程安全与 volatile与单例模式问题及解决方案

《Java线程安全与volatile与单例模式问题及解决方案》文章主要讲解线程安全问题的五个成因(调度随机、变量修改、非原子操作、内存可见性、指令重排序)及解决方案,强调使用volatile关键字... 目录什么是线程安全线程安全问题的产生与解决方案线程的调度是随机的多个线程对同一个变量进行修改线程的修改操