Saturday, November 17, 2018

Xamarin Forms RTL - Right to Left (Arabic support) - without restarting the app


This sample gives you a real time implementation of the RTL functionality in Xamarin forms. Setting up the framework for RTL is one time. Once properly set everything, 1 0r 2 lines of code update when you add new screens to your application. We take Arabic language for RTL and English for LTR.

Objective of this solution:
  • Code reusability (no repetitive codes in all screens)
  • App should launch with device's culture (If the phone device language is set to Arabic, the app should launch in Arabic mode)
  • Ability to save the user's language preferences (Phone device can be Arabic and the app language can be English or vice-versa)
iOS Sample video


Android Sample video


Step 1: Adding Resource Files


  1. Create solution with your preferred project name. It will create three projects in a solution - Xamarin, Android and iOS apps.
  2. Add a resource 'Resx' folder in the Xamarin app - Can add any resource files under this.
  3. Create another folder 'Lang' under 'Resx' for language files. 
  4. Right click on Lang folder and select 'Add New Item' - Add two resource files Strings.Resx and Strings.ar.Resx
  5. Add some default resource strings for our sample as below

English:
Arabic:

Step 2: Language Resource Loader

Create a helper class for language to get the respective resource strings based on the selected culture. You will get the full source code link at the end of this article. 

Key elements are,

  • It is a singleton class
  • It inherits INotifyPropertyChanged, to notify language change
  • It provides a property changed event, you can use anywhere in the app to get the event fired.
  • It provides the respective culture string based on the key provided.

So the, helper class would be as below.

Step 3: Supporting Classes


Global Enum and NotifyPropertyChanged classes are supporting files, just created in separate files for better understanding.

Step 4: Dependency Services

We need to use Dependency Service for saving user preferences and setting locale. So create Interface as below



1. IFileHelper - To save and retrieve users language preference.
2. ILocale - To get and set device locale.
Interface Implementations
Android FileHelper:
iOS FileHelper: Android Locale: iOS Locale: A helper class for setting the language, as below:
Step 5: Creating Baseviewmodel

We are going to create 3 common main properties in the baseviewmodel, which will be automatically set when we set the visual element for the viewmodel in the page code behind.

Page - Represent cross-platform mobile application screens. All the page types that are described below derive from the Xamarin.Forms Page class. These visual elements occupy all or most of the screen.
Visual ElementA Element that occupies an area on the screen, has a visual appearance, and can obtain touch input.
Flow DirectionDevice.FlowDirection is a helper that lets you know which direction the app should flow based on the device language and region. 

So the Baseviewmodel will be as below,
These properties are bindable properties, which will notify and update the visual element when the language is been changed.

How?

Baseviewmodel has another important property LangResourceLoader singleton class and it is subscribed to LanguagePropertyChanged event handler, with the below code: 
When there is a change in the language setting, this event will fire, which is setting the Flow Direction, which is a bindable property. So, when setting the flow direction, it is updating the Page flow direction.

Step 6: Creating page and viewmodel

  • Create a page called LoginPage
  • Create a View model called LoginPageViewModel
In the LoginPage.cs, set the visual element as below:
In the LoginPageViewModel, inherit the BaseViewModel and write a command for changing the language as below:   Step 7: Launching App

In the App.xaml.cs, add the codes for launching the app with device's language and culture. See the SetLanguage() code snippet in the below file.


Conclusion:

That's it. Try yourself and update your feedbacks. Full source code is here