Android 8.0 资源国际化适配

作者: Crazy_MT | 来源:发表于2017-12-11 00:05 被阅读1845次

    前言

    Android 8.0 发布已经有一段时间了,本文不讲新功能,讲讲资源国际化方面 Android 8.0 的踩坑及填坑经历。
    项目中要求应用内切换语言,并且不同语言也对应不同的语言字体(参考了这两个库 perfectLanguageUpdateNoNeedRestartFontometricsLibrary ),不同语言对应不同的布局文件。


    三个部分

    • 切换语言
    • 切换 layout 文件
    • 切换 raw 文件

    切换语言

    Android 8.0 之前切换语言只需要以下代码

    Resources resources = getContext().getResources();
    DisplayMetrics dm = resources.getDisplayMetrics();
    Configuration config = resources.getConfiguration();
    config.locale = Locale.ENGLISH; // 应用用户选择语言
    resources.updateConfiguration(config, dm);
    

    Android 8.0 切换语言需要以下代码

    Resources resources = getApplicationContext().getResources();
    DisplayMetrics dm = resources.getDisplayMetrics();
    Configuration config = resources.getConfiguration();
    config.setLocale(locale);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
          LocaleList localeList = new LocaleList(locale);
          LocaleList.setDefault(localeList);
          config.setLocales(localeList);
          getApplicationContext().createConfigurationContext(config);
    }
    Locale.setDefault(locale);
    resources.updateConfiguration(config, dm);
    

    重点: 确保 applicationContext 代替所有其它类型的 context。(至于针对 Android N 的那几行代码,实测好像没什么影响。)


    切换 layout 文件

    项目需求比较复杂,我的 layout 文件目录是这样的:

    image.png
    Android 8.0 之前,执行了上面代码,当你切换界面的时候,应该能显示对应语言下的 layout 文件。比如把 Locale 设置成中文简体,R.layout 文件将调用 layout-zh-rCN 目录下的界面,但是 Android 8.0 仍然执行了默认 layout 目录下面的界面。解决思路仍然是用 applicationContext 替代 context
    项目里对 layout 文件的使用有两处:
    • Activity 的 setContentView(R.layout.…)
    • Fragment 的 inflater.inflate(R.layout.…, container, false)
      针对 Fragment 容易解决,我发现 inflate 有两个重载方法
    public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) {……}
    public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {……}
    

    其中第二个方法的第一个参数 parser , 可以这样获得:getContext().getApplicationContext().getResources().getLayout(R.layout.…), 于是在 fragment 中获得布局文件就可以这样写 inflater.inflate(getContext().getApplicationContext().getResources().getLayout(R.layout.……), container, false);
    fragment 的问题解决了,activitysetContentView确没有相应的方法。解决方案也很粗暴,就是在 activity 中添加一个充满全局 fragment,然后将原 activity 的代码交由 fragment 管理,在 fragment 中获取多资源布局。


    切换 raw 文件

    为了给不同语言设置不同字体文件,参考并且修改了 FontometricsLibrary 的代码,现在我的 raw 目录是这样的:

    image.png 将 raw 转换成 InputStream 代码如下:
    InputStream mInputStream = context.getApplicationContext().getResources().openRawResource(R.raw.…);
    

    重点还是获得 applicationContext


    总结

    在 Android 8.0 国际化的时候,所有需要 context 的地方必须用 applicationContext

    Demo在此

    相关文章

      网友评论

        本文标题:Android 8.0 资源国际化适配

        本文链接:https://www.haomeiwen.com/subject/uqkbixtx.html