Resources and layout direction rendered incorrectly only on Android 8.0 and above

前端 未结 6 771
执念已碎
执念已碎 2020-11-29 11:06

I have a multilingual app with primary language English and secondary language Arabic.

I am calling setLocale() in the onCreate() of every

6条回答
  •  暗喜
    暗喜 (楼主)
    2020-11-29 11:50

    The updateConfiguration() method was deprecated

    Now we need to use createConfigurationContext()

    I have managed this way

    create a new class ContextWrapper

    import android.content.Context;
    import android.content.res.Configuration;
    import android.content.res.Resources;
    import android.os.Build;
    import android.os.LocaleList;
    
    import java.util.Locale;
    
    public class ContextWrapper extends android.content.ContextWrapper {
    
        public ContextWrapper(Context base) {
            super(base);
        }
    
        public static ContextWrapper wrap(Context context, Locale newLocale) {
    
            Resources res = context.getResources();
            Configuration configuration = res.getConfiguration();
    
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                configuration.setLocale(newLocale);
    
                LocaleList localeList = new LocaleList(newLocale);
                LocaleList.setDefault(localeList);
                configuration.setLocales(localeList);
    
                context = context.createConfigurationContext(configuration);
    
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                configuration.setLocale(newLocale);
                context = context.createConfigurationContext(configuration);
    
            } else {
                configuration.locale = newLocale;
                res.updateConfiguration(configuration, res.getDisplayMetrics());
            }
    
            return new ContextWrapper(context);
        }}
    

    create a new class of BaseActivity

    import android.content.Context;
    
    import android.support.v7.app.AppCompatActivity;
    
    import java.util.Locale;
    
    /**
     * Created by nilesh on 20/3/18.
     */
    
    public class BaseActivity extends AppCompatActivity {
    
        @Override
        protected void attachBaseContext(Context newBase) {
    
            Locale newLocale;
    
            String lang = new PrefManager(newBase).getLanguage();
    
            if (lang.equals("zh_CN")) {
                newLocale = new Locale("zh");
            } else {
                newLocale = new Locale(lang);
            }
    
    
            Context context = ContextWrapper.wrap(newBase, newLocale);
            super.attachBaseContext(context);
        }
    }
    

    Create a PrefManager class to store locale

    import android.content.Context;
    import android.content.SharedPreferences;
    
    public class PrefManager {
    
        private SharedPreferences.Editor editor;
        private Context mContext;
        private SharedPreferences prefs;
        private final String LANGUAGE = "language";
        private final String PREF = "user_data";
    
        public PrefManager(Context mContext) {
            this.mContext = mContext;
        }
    
        public String getLanguage() {
            this.prefs = this.mContext.getSharedPreferences(PREF, 0);
            return this.prefs.getString(LANGUAGE, "en_US");
        }
    
        public void setLanguage(String language) {
            this.editor = this.mContext.getSharedPreferences(PREF, 0).edit();
            this.editor.putString(LANGUAGE, language);
            this.editor.apply();
        }
    
    }
    

    Now you need to extends your BaseActivity in your all activity like

    public class OrdersActivity extends BaseActivity
    

    Now when your need to change Locale just update the value in PrefManager and restart your activity

        PrefManager prefManager= new PrefManager(this);
        prefManager.setLanguage("zh_CN");
        //  restart your activity
    

    NOTE

    You can download source code from github repo

提交回复
热议问题