Sunday 20 August 2017

Android RTL Feature

Android provides a feature to make our application bidirectional (LTR & RTL). This feature was introduced in android 4.1 (Jelly Bean) for TextView and EditText elements, allowing apps to display and edit text in both left-to-right (LTR) and right-to-left (RTL).

There was full support for RTL feature in android 4.2 version. It makes the exact mirror image of our existing layout.

Our application will continue to appear as we have set it in default direction. But, with a few simple changes, application will be automatically mirrored when the user switches the system language to a right-to-left script (such as Arabic, Hebrew, or Persian).


Android 4.2 includes the following APIs to help manage View components:
android:layoutDirection — attribute for setting the direction of a component’s layout.
android:textDirection — attribute for setting the direction of a component’s text.
android:textAlignment — attribute for setting the alignment of a component’s text.
getLayoutDirectionFromLocale() — method for getting the Locale-specified direction

Make these changes to support bidirectional feature by android:
  1. Add - android:supportsRtl="true" to the <application>element in manifest file.
  2. Change all of app’s “left/right” layout properties to new “start/end” equivalents.
·        If you are targeting your app to Android 4.2 (the app’s targetSdkVersion or minSdkVersion is 17 or higher), then you should use “start” and “end” instead of “left” and “right”. For example, android:paddingLeft should become android:paddingStart

·        If you want your app to work with versions earlier than Android 4.2 (the app’s targetSdkVersion or minSdkVersion is 16 or less), then you should add “start” and end” in addition to “left” and “right”. For example, you’d use both android:paddingLeft and android:paddingStart

Or

·        If you are using Android studio, then open your project in Android Studio and follow the steps:
                       1. Click on “Refactor” in android studio’s menu bar.
                       2. There will be a pop with options, reach to the end of the menu and click on
“Add RTL Support where possible”.
                       3. Now, you will get a popup. Tick the checkbox accordingly.

Note: If you are not a developer and still want to see the miracle then follow the steps:
  1. In your android phone, tap on “Settings” icon.
  2.   Scroll down the list. You will get “Developer options”, if not then no need to worry follow: Settings > About device > Build number
  3. Once you’ve found the Build number section of the settings, tap on the section 7 times. Now there will be “developer options” before “about phone”
  4.  Now tap on developer options and search for “Force RTL layout direction”.
  5. Tap on it to enable RTL feature.
This RTLUtils class helps us to know given View or Locale is RTL

package com.manakular.rajendhiran.lang;

import java.util.Collections;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;

import android.support.v4.view.ViewCompat;
import android.view.View;

public class RTLUtils
{

    private static final Set<String> RTL;

    static
    {
        Set<String> lang = new HashSet<String>();
        lang.add("ar"); // Arabic
        lang.add("dv"); // Divehi
        lang.add("fa"); // Persian (Farsi)
        lang.add("ha"); // Hausa
        lang.add("he"); // Hebrew
        lang.add("iw"); // Hebrew (old code)
        lang.add("ji"); // Yiddish (old code)
        lang.add("ps"); // Pashto, Pushto
        lang.add("ur"); // Urdu
        lang.add("yi"); // Yiddish
        RTL = Collections.unmodifiableSet(lang);
    }

    public static boolean isRTL(Locale locale)
    {
        if(locale == null)
            return false;

        // Character.getDirectionality(locale.getDisplayName().charAt(0))
        // can lead to NPE (Java 7 bug)
        // https://bugs.openjdk.java.net/browse/JDK-6992272?page=com.atlassian.streams.streams-jira-plugin:activity-stream-issue-tab
        // using hard coded list of locale instead
        return RTL.contains(locale.getLanguage());
    }

    public static boolean isRTL(View view)
    {
        if(view == null)
            return false;

        // config.getLayoutDirection() only available since 4.2
        // -> using ViewCompat instead (from Android support library)
        if (ViewCompat.getLayoutDirection(view) == View.LAYOUT_DIRECTION_RTL)
        {
            return true;
        }
        return false;
    }
}

To Identify RTL in Android:

public static boolean isRTL() {
    return isRTL(Locale.getDefault());
}

public static boolean isRTL(Locale locale) {
    final int directionality = Character.getDirectionality(locale.getDisplayName().charAt(0));
    return directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT ||
           directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC;
}

Also, you can takes the Android Lint's help to fix up the RTL.   Please refer and make use of the artifacts or library
Happy Coding :)

Tuesday 15 August 2017

Android Launch Mode

Activity is one of the most brilliant concept on Android from its well-design architecture on memory management which lets Multitasking works perfectly on this most popular mobile operating system. Anyway, Activity is not just to be launched on the screen. The way it is launched is also concerned. There are so many details in this topic. One of those that is really important is launchMode, which is the one that we are going to talk about in this blog.


There are 4 types of launchMode available. Let's see it one by one.
1. Standard
2. SingleTop
3. SingleTask
4. SingleInstance

1. Standard:  This is the default mode.  We are adding launchMode=”standard” in B.

Assume Activity Stack
D
C
B
A

Start Activity B again, Now the activity stack will be
B -new instance of B
D
C
B
A

2. SingleTop:  We are adding launchMode=”singleTop” in D.

Eg:1
Assume Activity Stack
D - is on top of Activity Stack
C
B
A

Start D from any service or other application or from somewhere.
Output:
D -old instance gets extras data through onNewIntent(Intent intent);
C
B
A

Note: if the activity available in the top of stack, it will update the same instance with new intent data or else it will create a new activity instance.

Eg: 2
Assume Activity Stack
D
C
B
A

Start C from D
Output:
C -As the last C was not on the top of task, so new instance will be created.
D
C
B
A

3. SingleTask: We are adding launchMode=”singleTask” in C.

Assume Activity Stack
D
C
B
A

Start C from any activity or service
Output:
C -old instance gets extras data through onNewIntent(Intent intent);
B
A

Note: it checks whether Activity C is available in the Stack, if yes, update the instance with new data and destroy the other activity at the top. Hence here Activity D gets destroyed.  if activity is unavailable in the stack it create a new instance as usual.

4. SingleInstance: We are adding launchMode=”singleInstance” in E.

Eg 1:
Assume Activity Stack
D
C
B
A

Start E
Output:
E
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
D
C
B
A

Note: A , B , C , D will be in one task and E will be in another task.
and if we continue this,  start F from E,then

Output:
F
D
C
B
A
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — -
E

Note: A , B , C , D , F will be in one task and E will be in another task.

Eg 2:
Assume Activity Stack
A
B
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — -
E

Start E from A
Output:
E -old instance gets extras data through onNewIntent(Intent intent);
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
A
B

Courtesy: Link1 & Link2