Android笔记本安卓学习Android收藏集

android更换语言

2019-01-31  本文已影响12人  crush_d872

工具类:

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

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

上一篇下一篇

猜你喜欢

热点阅读