Resources and Layout Direction Rendered Incorrectly Only on Android 8.0 and Above

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

The complete solution to this problem consists of three steps:

STEP 1:

In the onCreate() of your BaseActivity (or all your Activitys), set the Locale as follows:

@Override
protected void onCreate(Bundle savedInstanceState) {

// set the Locale the very first thing
Utils.setLocale(Utils.getSavedLocale());
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);

......
......

}

where getSavedLocale() is the Locale corresponding to the current region (this will be specific for your project ... ).

And the method Utils.setLocale(...) is defined as follows:

public static void setLocale(Locale locale){
Context context = MyApplication.getInstance();
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
Locale.setDefault(locale);
configuration.setLocale(locale);
configuration.setLayoutDirection(locale);

// updateConfiguration(...) is deprecated in N
if (Build.VERSION.SDK_INT >= 25) {
context = context.getApplicationContext().createConfigurationContext(configuration);
context = context.createConfigurationContext(configuration);
}

context.getResources().updateConfiguration(configuration,
resources.getDisplayMetrics());
}

This sets the correct Locale in every Activity. This is enough for apps supporting API level 25. For API level 26 & above, STEP 2 and STEP 3 are also required.

STEP 2:

Override the following method in your BaseActivity:

@Override
protected void attachBaseContext(Context newBase) {
newBase = Utils.getLanguageAwareContext(newBase);
super.attachBaseContext(newBase);
}

where the function getLanguageAwareContext(...) is defined as follows:

public static Context getLanguageAwareContext(Context context){
Configuration configuration = context.getResources().getConfiguration();
Locale locale = getIntendedLocale();
configuration.setLocale(locale);
configuration.setLayoutDirection(locale);
return context.createConfigurationContext(configuration);
}

This, along with STEP 1, sets the correct Locale in every Activity of your app for API level 26 and above.

One more step, however, is required for setting the language direction correctly ...

STEP 3:

In the onCreate() of your BaseActivity, add the following code:

@Override
protected void onCreate(Bundle savedInstanceState) {

....
....

// yup, it's a legit bug ... :)
if (Build.VERSION.SDK_INT >= 26) {
getWindow().getDecorView().setLayoutDirection(Utils.isRTL()
? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);

}

....
....
}

where the isRTL() function is defined as follows:

public static boolean isRTL(){
return TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) == View.LAYOUT_DIRECTION_RTL;
}

The above steps should take care of all issues (at least regarding setting the Locale and text direction) on all extant versions of Android.

RTL layout bug in android Oreo

Simple fix in your onCreate function add the following code:

if (Locale.getDefault().getLanguage()=="ar")
getWindow().getDecorView().setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
else
getWindow().getDecorView().setLayoutDirection(View.LAYOUT_DIRECTION_LTR);

Unable to change language in Oreo

When you set new Locale you should restart your Activity. You can perform it using the next snippet of code:

private void restartActivity() {
Intent intent = getIntent();
finish();
startActivity(intent);
}

Then your changeLanguage() method will look in a next way:

public void changeLanguage(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Configuration config = context.getResources().getConfiguration();
config.setLocale(locale);
context.createConfigurationContext(config);
context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());

restartActivity();
}

RTL not Support after removing app from recent (killing)

After doing lots of R&D I found this. Tried this and issue has been resolved

Android RTL issue in API 24 and higher on locale change

The problem seems to be that it doesn't reflect layout direction changes at first update. I solved the problem by overriding the onAttachedToWindow method of Activity like below:

@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
getWindow().getDecorView().setLayoutDirection(
"ur".equals(LocaleHelper.getLanguage(this)) ?
View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
}
}

Tested on API 25 and it's working fine. Be careful though I'm not sure about any side effects for this approach at this moment. Nevertheless, I think it is what you are looking for.

I'll also update the blog post to reflect more elegant, generic code for this.

RecyclerView not changing resource values when language change

i found the solution.

i call this in the constructor of Recyclerview adapter. i dont know if it is the correct method,still my problem is solved

 @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
public static void setResources(Context context) {
Locale locale;

Sessions session = new Sessions(context);
//Log.e("Lan",session.getLanguage());
if (session.getLanguage().equals("1")) {
locale = new Locale("en-rUS");
}else{
locale = new Locale("ar");
}

Resources res=context.getResources();
DisplayMetrics dm=res.getDisplayMetrics();
android.content.res.Configuration configuration=res.getConfiguration();
configuration.setLocale(locale);
res.updateConfiguration(configuration,dm);
}

How to change Android O / Oreo / api 26 app language

I had the same problem: since Android 8.0+ some parts of my app did't change their language anymore. Updating of both application and activity context helps me. Here is an example of MainActivity function:

private void setApplicationLanguage(String newLanguage) {
Resources activityRes = getResources();
Configuration activityConf = activityRes.getConfiguration();
Locale newLocale = new Locale(newLanguage);
activityConf.setLocale(newLocale);
activityRes.updateConfiguration(activityConf, activityRes.getDisplayMetrics());

Resources applicationRes = getApplicationContext().getResources();
Configuration applicationConf = applicationRes.getConfiguration();
applicationConf.setLocale(newLocale);
applicationRes.updateConfiguration(applicationConf,
applicationRes.getDisplayMetrics());
}


Related Topics



Leave a reply



Submit