坏耶,是 Rikka

大概主要会放一些和 Android 有关的东西吧

记一个在做切换 Activity 语言时遇到的小坑(要把 Google 的人 吊起来 打)

一句话说明 Rikka 的实现

ActivityattachBaseContext 中返回使用 createConfigurationContext 创建的 locale 不同的 Context

遇到的坑

在 LTR 和 RTL 语言之间切换时,第一次没问题,但从第二次开始就会出现布局方向相反的问题(想自己体验一下这个问题的话可以试试 Google 刚出的 File Go)。

Rikka 觉得这个锅 framework 要背(而且记得之前还遇到个什么也是这样第一次可以第二次就炸裂的),但是精力有限没办法去调查具体的原因了(要把 Google 的人 吊起来 打(

完整的的实现(和解决办法)

(解决方法是在 ActivityonCreate 时手动设置一下 DecorView 的 LayoutDirection)

public class LocaleDelegate {

    /** current locale **/
    private static Locale sDefaultLocale = Locale.getDefault();

    /** locale of this instance **/
    private Locale mLocale = Locale.getDefault();

    /**
     * Get default locale stored in this class.
     *
     * @return default locale
     */
    public static Locale getDefaultLocale() {
        return sDefaultLocale;
    }

    /**
     * Set default locale, this will not call {@link Locale#setDefault(Locale)}.
     *
     * @param newLocale new locale
     */
    public static void setDefaultLocale(Locale newLocale) {
        sDefaultLocale = newLocale;
    }

    /**
     * Return if current locale is different from default.
     * <p>Call this in {@link Activity#onResume()} and if true you should recreate activity.
     *
     * @return locale changed
     */
    public boolean isLocaleChanged() {
        return !Objects.equals(sDefaultLocale, mLocale);
    }

    /**
     * Update locale of context's configuration, call in {@link Activity#attachBaseContext(Context)}.
     *
     * @param newBase newBase
     * @return a new context instance with updated configuration
     */
    public Context onAttachBaseContext(Context newBase) {
        if (Objects.equals(mLocale, sDefaultLocale)) {
            return newBase;
        }

        mLocale = sDefaultLocale;

        Configuration configuration = newBase.getResources().getConfiguration();
        configuration.setLocale(mLocale);

        return newBase.createConfigurationContext(configuration);
    }

    /**
     * A dirty fix for wrong layout direction after switching locale between LTR and RLT language,
     * call in {@link Activity#onCreate(Bundle)}.
     *
     * @param activity Activity
     */
    public void onCreate(Activity activity) {
        activity.getWindow().getDecorView().setLayoutDirection(TextUtils.getLayoutDirectionFromLocale(mLocale));
    }
}