android更换语言

工具类:

public class MultiLanguageUtil {

private static final String TAG = "MultiLanguageUtil";
private static MultiLanguageUtil instance;
private Context mContext;
public static final String SAVE_LANGUAGE = "save_language";

public static void init(Context mContext) {
    if (instance == null) {
        synchronized (MultiLanguageUtil.class) {
            if (instance == null) {
                instance = new MultiLanguageUtil(mContext);
            }
        }
    }
}

public static MultiLanguageUtil getInstance() {
    if (instance == null) {
        throw new IllegalStateException("You must be init MultiLanguageUtil first");
    }
    return instance;
}

private MultiLanguageUtil(Context context) {
    this.mContext = context;
}

/**
 * 设置语言
 */
public void setConfiguration() {
    Locale targetLocale = getLanguageLocale();
    Configuration configuration = mContext.getResources().getConfiguration();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        configuration.setLocale(targetLocale);
    } else {
        configuration.locale = targetLocale;
    }
        Resources resources = mContext.getResources();
        DisplayMetrics dm = resources.getDisplayMetrics();
        resources.updateConfiguration(configuration, dm);//语言更换生效的代码!
}

/**
 * 如果不是英文、简体中文、繁体中文,默认返回简体中文
 *
 * @return
 */
private Locale getLanguageLocale() {
    int languageType = CommSharedUtil.getInstance(mContext).getInt(MultiLanguageUtil.SAVE_LANGUAGE, 0);

    if (languageType == LanguageType.LANGUAGE_CHINESE) {
        return new Locale("en", "ZA");
    } else {
        Locale sysLocale= Locale.CHINESE;
        return sysLocale;
    }


private String getSystemLanguage(Locale locale) {
    return locale.getLanguage() + "_" + locale.getCountry();

}

//以上获取方式需要特殊处理一下
public Locale getSysLocale() {
    Locale locale;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        locale = LocaleList.getDefault().get(0);
    } else {
        locale = Locale.getDefault();
    }
    return locale;
}

/**
 * 更新语言
 *
 * @param languageType
 */
public void updateLanguage(int languageType) {
    CommSharedUtil.getInstance(mContext).putInt(MultiLanguageUtil.SAVE_LANGUAGE, languageType);
    MultiLanguageUtil.getInstance().setConfiguration();
}

public String getLanguageName(Context context) {
    int languageType = CommSharedUtil.getInstance(context).getInt(MultiLanguageUtil.SAVE_LANGUAGE,LanguageType.LANGUAGE_UYGUR);
    if (languageType == LanguageType.LANGUAGE_CHINESE) {
        return mContext.getString(R.string.setting_language_chinese);
    }
    return mContext.getString(R.string.setting_language_uygur);
}

/**
 * 获取到用户保存的语言类型
 * @return
 */
public int getLanguageType() {
    int languageType = CommSharedUtil.getInstance(mContext).getInt(MultiLanguageUtil.SAVE_LANGUAGE, LanguageType.LANGUAGE_UYGUR);
    if (languageType == LanguageType.LANGUAGE_CHINESE) {
       return LanguageType.LANGUAGE_CHINESE;
    }
    return languageType;
}

public static Context attachBaseContext(Context context) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        return createConfigurationResources(context);
    } else {
        MultiLanguageUtil.getInstance().setConfiguration();
        return context;
    }
}

@TargetApi(Build.VERSION_CODES.N)
private static Context createConfigurationResources(Context context) {
    Resources resources = context.getResources();
    Configuration configuration = resources.getConfiguration();
    Locale locale=getInstance().getLanguageLocale();
    configuration.setLocale(locale);
    return context.createConfigurationContext(configuration);
}

}

使用方法:

1.在MyApplication里加如下代码:

MultiLanguageUtil.init(this);//初始化

2.在BaseActivity中加入:

@Override
protected void attachBaseContext(Context newBase) {
    super.attachBaseContext(MultiLanguageUtil.attachBaseContext(newBase));
}

遇到的问题:

1. 横竖屏切换(屏幕旋转)导致多语言(国际化)的设置失效

原因:当屏幕旋转横竖屏切换时,Activity的onConfigurationChanged方法使用了系统的语言设置,Activity中onConfigurationChanged的源码如下:

    @Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    getDelegate().onConfigurationChanged(newConfig);
    if (mResources != null) {
        // The real (and thus managed) resources object was already updated
        // by ResourcesManager, so pull the current metrics from there.
        final DisplayMetrics newMetrics = super.getResources().getDisplayMetrics();
        mResources.updateConfiguration(newConfig, newMetrics);
    }
}

从上面的代码中我们可以看到newConfig取的是系统的,这就解释了为什么APP明明设置成了繁体,但是打开一个横屏页面之后,发现APP又重置成了简体,就是这个方法导致的。

所以我们只需要在onConfigurationChanged方法中,重新设置为我们用户选择的语言配置就可以了。因为要在所有的Activity中的onConfigurationChanged中设置会有些麻烦,我们可以在application中的onConfigurationChanged方法中统一设置,这样就可以解决屏幕旋转造成的多语言失效问题。

 @Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    MultiLanguageUtil.getInstance().setConfiguration();
}
2. 打开有 webview 的Activity会导致多语言失效,发生在Android7.0以上

原因:可能是webview在加载的过程中也会重新设置系统的语言,这样因为打开网站可能有英文版的和中文的。
  解决方案,既然很多情况下都会造成多语言失效,不如我们统一在BaseActivity的onCreate方法中都设置

                LanguageUtil.getInstance().setConfiguration();

当然如果有些Activity不是继承子BaseActivity,我们依然可以在application中的onCreate方法中使用这样的方式来拿到整个应用的所有activity的生命周期方法,然后在这样设置:

 registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
        @Override
        public void onActivityCreated(Activity activity, Bundle bundle) {

        }

        @Override
        public void onActivityStarted(Activity activity) {

        }

        @Override
        public void onActivityResumed(Activity activity) {
            MultiLanguageUtil.getInstance().setConfiguration();
        }

        @Override
        public void onActivityPaused(Activity activity) {

        }

        @Override
        public void onActivityStopped(Activity activity) {

        }

        @Override
        public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {

        }

        @Override
        public void onActivityDestroyed(Activity activity) {

        }
    });
3. 使用微信开源的热修复框架Tinker,打了包含资源的补丁之后会导致多语言失效

在试用的过程中遇到如果打了包含资源string文件的补丁之后,会导致多语言失效,本来选的繁体变成了简体语言,同时无论你怎么切换语言,都没有生效。这属于Tinker的bug,已经有人在Tinker的github主页上反馈了,但是这个issue 任然没有关闭:(https://github.com/Tencent/tinker/issues/302) 。

4.在build.gradle文件配置问题:

第一个是版本问题,这个问题的回答比较多,我遇到的问题如下,设置了:


image.png

导致语言切换无作用,这是在对接各大手机市场的平台时配置的,所以注意这个问题。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容