Itiel Maimon Itiel Maimon - 27 days ago 14
Android Question

How to create RTL ViewPager?

I'm using ViewPager in my application and I want to support RTL, but when I cahnge my device language to RTl it seems it does'nt working.

I want the tabs to start from the right side (the first fragment in the right).

Please help me to solve it.

EDIT: Here is a picture of it:
Tabs start from the left side

Here is my code:

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<include
layout="@layout/app_bar_main"
android:id="@+id/toolbar_actionbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

<android.support.v4.widget.DrawerLayout
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:openDrawer="start"
android:layout_below="@id/toolbar_actionbar">

<android.support.design.widget.CoordinatorLayout
android:id="@+id/fragment_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

<com.google.android.gms.ads.AdView
android:id="@+id/adView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
ads:adSize="BANNER"
ads:adUnitId="@string/banner_ad_unit_id"
android:layout_gravity="center_horizontal|bottom"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true">
</com.google.android.gms.ads.AdView>

</android.support.design.widget.CoordinatorLayout>

<android.support.design.widget.NavigationView
android:id="@+id/nav_view"
android:layout_width="250dp"
android:layout_height="match_parent"
android:layout_gravity="start"
app:menu="@menu/activity_main_drawer"/>

</android.support.v4.widget.DrawerLayout>

</RelativeLayout>

</android.support.design.widget.CoordinatorLayout>


MainActivity.java:

package ...;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.design.widget.NavigationView;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.GravityCompat;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;

import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdView;
import com.google.android.gms.ads.InterstitialAd;

import java.util.ArrayList;
import java.util.List;


public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {

InterstitialAd mInterstitialAd;

@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(R.style.AppTheme_NoActionBar);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
setTitle(getString(R.string.app_name));

ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);

TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);

mInterstitialAd = new InterstitialAd(this);
mInterstitialAd.setAdUnitId(getString(R.string.interstitial_ad_unit_id));

mInterstitialAd.setAdListener(new AdListener() {
@Override
public void onAdClosed() {
requestNewInterstitial();
}
});

requestNewInterstitial();

AdView mAdView = (AdView) findViewById(R.id.adView);
AdRequest adRequest = new AdRequest.Builder().build();
mAdView.loadAd(adRequest);


DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();

NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}

private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new Intro(), getString(R.string.Introduction));
adapter.addFragment(new S1(), getString(R.string.stage1));
adapter.addFragment(new S2(), getString(R.string.stage2));
adapter.addFragment(new S3(), getString(R.string.stage3));
adapter.addFragment(new S4(), getString(R.string.stage4));
adapter.addFragment(new S5(), getString(R.string.stage5));
adapter.addFragment(new S6(), getString(R.string.stage6));
adapter.addFragment(new S7(), getString(R.string.stage7));
viewPager.setAdapter(adapter);
}

class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();

public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}

@Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}

@Override
public int getCount() {
return mFragmentList.size();
}

public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}

@Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}


@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();

switch (id) {
case R.id.action_contact_us: {
Intent browserIntent1 = new Intent(Intent.ACTION_VIEW,
Uri.parse(getString(R.string.Contact_us_URL)));
startActivity(browserIntent1);
return true;
}
case R.id.action_share: {
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
String shareBody = getString(R.string.shareText);
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, shareBody);
startActivity(Intent.createChooser(sharingIntent, getString(R.string.share_via)));
return true;
}
case R.id.action_rate_us: {
Intent browserIntent2 = new Intent(Intent.ACTION_VIEW,
Uri.parse(getString(R.string.Rate_us_URL)));
startActivity(browserIntent2);
return true;
}
case R.id.action_help: {
final Intent intent1 = new Intent(MainActivity.this, HelpActivity.class);
if (mInterstitialAd.isLoaded()) {
mInterstitialAd.show();
mInterstitialAd.setAdListener(new AdListener() {
public void onAdClosed() {
requestNewInterstitial();
startActivity(intent1);
}
});
}
else {
startActivity(intent1);
}
return true;
}
case R.id.action_about_us: {
final Intent intent2 = new Intent(MainActivity.this, AboutActivity.class);
if (mInterstitialAd.isLoaded()) {
mInterstitialAd.show();
mInterstitialAd.setAdListener(new AdListener() {
public void onAdClosed() {
requestNewInterstitial();
startActivity(intent2);
}
});
}
else {
startActivity(intent2);
}
return true;
}
case R.id.action_settings: {
Intent intent3 = new Intent(MainActivity.this, SettingsActivity.class);
startActivity(intent3);
return true;
}
}
return super.onOptionsItemSelected(item);
}

@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();

switch (id){

case R.id.action_contact_us:
Intent browserIntent1 = new Intent(Intent.ACTION_VIEW,
Uri.parse(getString(R.string.Contact_us_URL)));
startActivity(browserIntent1);
break;

case R.id.action_share:
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
String shareBody = getString(R.string.shareText);
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, shareBody);
startActivity(Intent.createChooser(sharingIntent, getString(R.string.share_via)));
break;

case R.id.action_rate_us:
Intent browserIntent2 = new Intent(Intent.ACTION_VIEW,
Uri.parse(getString(R.string.Rate_us_URL)));
startActivity(browserIntent2);
break;

case R.id.action_help:
final Intent intent1 = new Intent(MainActivity.this, HelpActivity.class);
if (mInterstitialAd.isLoaded()) {
mInterstitialAd.show();
mInterstitialAd.setAdListener(new AdListener() {
public void onAdClosed() {
requestNewInterstitial();
startActivity(intent1);
}
});
}
else {
startActivity(intent1);
}
break;

case R.id.action_about_us:
final Intent intent2 = new Intent(MainActivity.this, AboutActivity.class);
if (mInterstitialAd.isLoaded()) {
mInterstitialAd.show();
mInterstitialAd.setAdListener(new AdListener() {
public void onAdClosed() {
requestNewInterstitial();
startActivity(intent2);
}
});
}
else {
startActivity(intent2);
}
break;

case R.id.action_settings:
Intent intent3 = new Intent(this, SettingsActivity.class);
startActivity(intent3);
break;
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}

private void requestNewInterstitial() {
AdRequest adRequest = new AdRequest.Builder().build();
mInterstitialAd.loadAd(adRequest);
}


}

Thank you!!!

Answer

After a lot of research I realized how to do it. What I needed to do is to reverse the order of the fragments (when initialize them to the ViewPager) and do viewPager.setCurrentItem(ViewPagerSize). But it's has to happen only if the locale is RTL so I used a method to determine if it is.

This is the code:

 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;
 }

private void setupViewPager(ViewPager viewPager) {
    ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
    if (isRTL()) {
        // The view has RTL layout
        adapter.addFragment(new S7(), getString(R.string.stage7));
        adapter.addFragment(new S6(), getString(R.string.stage6));
        adapter.addFragment(new S5(), getString(R.string.stage5));
        adapter.addFragment(new S4(), getString(R.string.stage4));
        adapter.addFragment(new S3(), getString(R.string.stage3));
        adapter.addFragment(new S2(), getString(R.string.stage2));
        adapter.addFragment(new S1(), getString(R.string.stage1));
        adapter.addFragment(new Intro(), getString(R.string.Introduction));
    } else {
        // The view has LTR layout
        adapter.addFragment(new Intro(), getString(R.string.Introduction));
        adapter.addFragment(new S1(), getString(R.string.stage1));
        adapter.addFragment(new S2(), getString(R.string.stage2));
        adapter.addFragment(new S3(), getString(R.string.stage3));
        adapter.addFragment(new S4(), getString(R.string.stage4));
        adapter.addFragment(new S5(), getString(R.string.stage5));
        adapter.addFragment(new S6(), getString(R.string.stage6));
        adapter.addFragment(new S7(), getString(R.string.stage7));
    }
    viewPager.setAdapter(adapter);
}

And for the tabs I had to set the direction to LTR (It's looks messy when it's RTL).

So I used this code (It's only available in API 17+):

 TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        tabLayout.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
    }

I could'nt find a way to do this on pre API 17.