簡(jiǎn)述
當(dāng)APP需要給提供多種語(yǔ)音供用戶使用的時(shí)候,作為開(kāi)發(fā)者的我們自然要涉及到多語(yǔ)言切換的開(kāi)發(fā),希望我提供的方式能給需要的小伙伴們一點(diǎn)思路,老規(guī)矩先上圖。
效果如下,可能看起來(lái)會(huì)比較卡(不知道為啥黑屏?xí)r間卡了好久,實(shí)際效果是一閃而過(guò))

實(shí)現(xiàn)方式
這是最常運(yùn)用的最普遍的方式,通過(guò)創(chuàng)建不同的value 語(yǔ)言文件夾下的的string.xml ,當(dāng)更改時(shí),切換使用對(duì)應(yīng)的字符資源。
讓我們先來(lái)創(chuàng)建對(duì)應(yīng)的字符資源文件夾。在main目錄下的res文件夾右鍵新建一個(gè)資源文件夾

選中Locale,導(dǎo)入限定資源里

此時(shí)會(huì)出現(xiàn)各種語(yǔ)言資源,在此項(xiàng)目中,我將新增中文(zh)與英文(en)字符資源 (懶得找的小伙伴其實(shí)只要知道對(duì)應(yīng)的語(yǔ)言文化代碼,直接自己創(chuàng)建命名也可)

建完之后的目錄:

接著再導(dǎo)入本次要使用的EventBus,用于廣播通知(也可用Broadcast,這次主要是對(duì)于語(yǔ)言切換的實(shí)現(xiàn),故不展開(kāi)講)
implementation 'org.greenrobot:eventbus:3.0.0'
然后我們先來(lái)實(shí)現(xiàn)一個(gè)抽象基類:BaseActivity,讓其它Activity繼承其特性,寫(xiě)一些共有方法,便于我們維護(hù)何使用,這里是為了實(shí)現(xiàn)多語(yǔ)言切換時(shí),不用在每個(gè)Activity中實(shí)現(xiàn)切換語(yǔ)言通知時(shí),界面重建與減少繁瑣的編寫(xiě)EventBus 的訂閱與注銷
public abstract class BaseActivity extends AppCompatActivity {
public final static String SWITCH_LANGUAGE = "Language";
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setLanguage();
EventBus.getDefault().register(this);
setContentView(getViewResId());
init();
}
protected void init() {
}
protected abstract int getViewResId();
@Override
protected void onDestroy() {
EventBus.getDefault().unregister(this);
super.onDestroy();
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(String msg) {
switch (msg){
case SWITCH_LANGUAGE:
setLanguage();
recreate();//刷新界面
break;
}
}
private void setLanguage() {
Locale myLocale = new Locale(SPUtils.getLanguage(this));
Resources res = getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
conf.locale = myLocale;
res.updateConfiguration(conf, dm);
}
}
setLanguage()方法中設(shè)置了我們的地理語(yǔ)言環(huán)境,將我們?cè)O(shè)置Locale賦值給Configuration,設(shè)置為我們需要的語(yǔ)言環(huán)境,再調(diào)用 recreate()方法銷毀界面再重新創(chuàng)建,此方法只有在API>26以上版本才存在。調(diào)用后新創(chuàng)建的活動(dòng)的生命周期:onCreate->onStart->onResume
其中SPUtils 工具類是用來(lái)在關(guān)閉應(yīng)用后,重新打開(kāi)我們的APP時(shí),記錄用戶設(shè)置的切換語(yǔ)言類型(它本質(zhì)就是一個(gè)小型數(shù)據(jù)庫(kù),隨著應(yīng)用卸載而被銷毀)
public class SPUtils {
public static void setLanguage(Context context, String language) {
SharedPreferences.Editor editor = context.getSharedPreferences("Language", context.MODE_PRIVATE).edit();
editor.putString("language", language);
editor.commit();
}
public static String getLanguage(Context context) {
SharedPreferences editor = context.getSharedPreferences("Language", context.MODE_PRIVATE);
return editor.getString("language","zh");//默認(rèn)中文
}
}
回到我們的主界面來(lái),在XML上直接使用我們?cè)趕trings中定義的內(nèi)容,復(fù)制strings到對(duì)values-en 與 values-zh,自行修改中文與英文的的內(nèi)容



在XML上的使用是通過(guò)@string/name 方式設(shè)置

在代碼中則是通過(guò)調(diào)用Resources 的getString 方法獲取對(duì)應(yīng)資源文件的id來(lái)設(shè)置
getResources().getString(R.string.to_one)
現(xiàn)在我們通過(guò)跳轉(zhuǎn)ActivityOne(記得要繼承我們編寫(xiě)的基類)界面,點(diǎn)擊按鈕切換語(yǔ)言,XML布局就不給出了
public class ActivityOne extends BaseActivity {
@Override
protected void init() {
onClickEvent();
}
@Override
protected int getViewResId() {
return R.layout.activity_one;
}
private void onClickEvent() {
findViewById(R.id.tv_chinese).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SPUtils.setLanguage(ActivityOne.this, "zh");
EventBus.getDefault().post(BaseActivity.SWITCH_LANGUAGE);
}
});
findViewById(R.id.tv_english).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SPUtils.setLanguage(ActivityOne.this, "en");
EventBus.getDefault().post(BaseActivity.SWITCH_LANGUAGE);
}
});
}
}
至此,就實(shí)現(xiàn)了語(yǔ)言切換的功能,錄制圖已貼在最頂部,當(dāng)然切換方法還有其它方式,這里給出較為常用的一種,希望能給需要的小伙伴們一點(diǎn)啟發(fā)。