Android 多语言切换无需重启APP的方式

简述

当APP需要给提供多种语音供用户使用的时候,作为开发者的我们自然要涉及到多语言切换的开发,希望我提供的方式能给需要的小伙伴们一点思路,老规矩先上图。

效果如下,可能看起来会比较卡(不知道为啥黑屏时间卡了好久,实际效果是一闪而过)


效果图.gif

实现方式

这是最常运用的最普遍的方式,通过创建不同的value 语言文件夹下的的string.xml ,当更改时,切换使用对应的字符资源。
让我们先来创建对应的字符资源文件夹。在main目录下的res文件夹右键新建一个资源文件夹


操作截图1.png

选中Locale,导入限定资源里


操作截图2.png

此时会出现各种语言资源,在此项目中,我将新增中文(zh)与英文(en)字符资源 (懒得找的小伙伴其实只要知道对应的语言文化代码,直接自己创建命名也可)


操作截图3.png

建完之后的目录:


操作截图4.png

接着再导入本次要使用的EventBus,用于广播通知(也可用Broadcast,这次主要是对于语言切换的实现,故不展开讲)

implementation 'org.greenrobot:eventbus:3.0.0'

然后我们先来实现一个抽象基类:BaseActivity,让其它Activity继承其特性,写一些共有方法,便于我们维护何使用,这里是为了实现多语言切换时,不用在每个Activity中实现切换语言通知时,界面重建与减少繁琐的编写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()方法中设置了我们的地理语言环境,将我们设置Locale赋值给Configuration,设置为我们需要的语言环境,再调用 recreate()方法销毁界面再重新创建,此方法只有在API>26以上版本才存在。调用后新创建的活动的生命周期:onCreate->onStart->onResume
其中SPUtils 工具类是用来在关闭应用后,重新打开我们的APP时,记录用户设置的切换语言类型(它本质就是一个小型数据库,随着应用卸载而被销毁)

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");//默认中文
    }
}

回到我们的主界面来,在XML上直接使用我们在strings中定义的内容,复制strings到对values-en 与 values-zh,自行修改中文与英文的的内容


目录文件.png
zh\string.png
en\string.png

在XML上的使用是通过@string/name 方式设置

操作截图5.png

在代码中则是通过调用Resources 的getString 方法获取对应资源文件的id来设置

getResources().getString(R.string.to_one)

现在我们通过跳转ActivityOne(记得要继承我们编写的基类)界面,点击按钮切换语言,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);
            }
        });
    }
}

至此,就实现了语言切换的功能,录制图已贴在最顶部,当然切换方法还有其它方式,这里给出较为常用的一种,希望能给需要的小伙伴们一点启发。

你可能感兴趣的:(Android 多语言切换无需重启APP的方式)