Change Locale in runtime
Android supports multi-language. During Android apps development, we put the locale-specific text in different String.xml files. Android apps will load the corresponding text defined in String.xml according to the system locale setting at startup. However, in some case, we may want to switch the locale in the app differently to the system setting. We can change the Locale in Activity or Fragment.
Change Locale
We access Context -> Resource -> Configuration and set LocaleConfiguration configuration = getResources().getConfiguration(); configuration.setLocale(selectedLanguage); getResources().updateConfiguration(configuration, getResources().getDisplayMetrics());
- Change the Locale inside Activity and restart Activity:
Configuration configuration = getResources().getConfiguration(); configuration.locale = selectedLanguage; getResources().updateConfiguration(configuration, getResources().getDisplayMetrics()); getActivity().recreate();
- Change Locale inside a Fragment and navigate up immediately:
Configuration configuration = getResources().getConfiguration(); configuration.locale = selectedLanguage; getResources().updateConfiguration(configuration, getResources().getDisplayMetrics()); Navigation.findNavController(v).navigateUp();
Problems
However, I have met below problems:If the app is currently connected to devices, bluetooth devices for example, it will disconnect once you restart Activity.
When the Activity restarts and the fragment(in which recreated() is called ) is popped up. The title of the toolbar(if there is) becomes the name of the app. When I navigate to another fragment, the title of the toolbar resumes normal text with the new Locale. Similar problem happened when I change locale inside Fragment.
After setting a new Locale, the text(whole apop) changes back to the previous Locale form when I first navigate to a fragment containing the UI component WebView.
- To restart Activity, the Android system must first destroy the existing Activity. The connection between the devices is lost when the existing Activity is destroyed . There we change the locale inside a fragment, instead of restarting Activity. The existing Activity keeps alive.
- We set the title of ActionBar in each Fragment ‘s onViewCreated() method. Therefore, each Fragment must update the title according to new Locale when it is created.
@Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState){ super.onViewCreated(view, savedInstanceState); ActionBar bar = ((AppCompatActivity) getActivity()).getSupportActionBar(); bar.setTitle(R.string.actionBarTitle); bar.show(); .......
- WebView is the system module and is running in a sandbox. It is not bound by the app Locale but the system Locale. Therefore, we need to store the app Locale before inflating the layout which contains WebView.
Then we set the Locale again after inflating the layout.
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) displayedLocale = getResources().getConfiguration().getLocales().get(0); else displayedLocale = getResources().getConfiguration().locale; return inflater.inflate(R.layout.fragment_sample, container, false); }
Now WebView can load the content with correct content and do not affect app Locale.@Override public void onViewCreated(View view, Bundle saveInstanceState){ super.onViewCreated(view, saveInstanceState); Resources res = getResources(); Configuration configuration = res.getConfiguration(); configuration.setLocale(displayedLocale); getResources().updateConfiguration(configuration, res.getDisplayMetrics()); WebView mWebView = (WebView) view.findViewById(R.id.my_webview); .........
留言
發佈留言