关于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列举一次,如果是多语言支持的自定义控件,就更新它,详细步骤看下文:
建立多语言文件夹,并写好多语言所需的文字
values-zh
values-en
…..
不细讲了
定义多语言切换接口,需要自定义view实现它
在控件包(widget包)下建立AppTextView和AppButton
建立接口:LanguageView,包含以下方法:
//由于setText无法被重写,需要添加以下三个必要的方法,如果你的app不需要对多语言的textview修改值(只是xml写死就够了),那就不需要实现他们
void setTextById (@StringRes int id);//手动设置textId
void setTextWithString (String text);//手动去掉textId,不然重新加载语言的时候会被重置掉
void setTextByArrayAndIndex (@ArrayRes int arrId, @StringRes int arrIndex);//手动通过TextArray设置语言
void reLoadLanguage();//修改语言时主要调用的方法
自定义多语言切换view:
public class AppTextView extends TextView implements LanguageView {
private int textId ;//文字id
private int hintId ;//hint的id
private 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,去掉@号就是资源id
textId = 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()));
}
}
}
@Override
public void setTextById (@StringRes int strId) {
this.textId = strId;
setText(strId);
}
@Override
public void setTextWithString(String text) {
this.textId = 0;
setText(text);
}
@Override
public void setTextByArrayAndIndex (@ArrayRes int arrId, @StringRes int arrIndex) {
arrResId = arrId;
arrResIndex = arrIndex;
String[] strs = getContext().getResources().getStringArray(arrId);
setText(strs[arrIndex]);
}
@Override
public 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();
}
}
}
博客出处
编写xml:
<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>
写好activity代码后,添加eventbus,实现activity之间的通信(用其它方式实现通信也行)
gradle添加 compile 'org.greenrobot:eventbus:3.0.0'
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EventBus.getDefault().register(this);
findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
@Override
public 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
}
@Override
protected void onDestroy(){
super.onDestroy();
EventBus.getDefault().unregister(this);//反注册EventBus
}
}
编写修改多语言文字的代码:
//给给出一个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