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 Activity
s), 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
How to Solve Render Problem Path.Op() Not Supported
Android 4.3 and Phonegap, Cant Tap Link
How to Clear the Volley Cache Automatically
How to Get Activity in Compose
App Crashes on Startup Due to Java.Lang.Illegalargumentexception: Column '_Id' Does Not Exist
Android.App.Application Cannot Be Instantiated Due to Nullpointerexception
How to Implement Search in Customlistview Based on Class Item of Pojo Class in Android
Android: Create a Toggle Button with Image and No Text
Pcm -> Aac (Encoder) -> Pcm(Decoder) in Real-Time with Correct Optimization
Android Input Connection Error
Android/View/View$Onunhandledkeyeventlistener (Onmeasure Error)
Android: HTML Anchor Link Works Only Once in Webview
How to Get Android Avd Name from Adb Device Name
Addoncompletelistener Not Called Offline with Cloud Firestore
Getting Net::Err_Unknown_Url_Scheme While Calling Telephone Number from HTML Page in Android
How to Keep The Oauth Consumer Secret Safe, and How to React When It's Compromised