How to create RTL ViewPager?

冷暖自知 提交于 2019-11-27 16:16:14

问题


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!!!


回答1:


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.




回答2:


this library RtlViewPager Does the job cleanly

only requires replacing

<android.support.v4.view.ViewPager

with

<com.duolingo.open:rtl-viewpager

in the XML

it also supports tabLayout

using this approach is cleaner since it doesn't require reversing the Adapter logic

Also see this issue report for google




回答3:


My solution is adding android:rotationY="@integer/view_pager_rotation" attribute to viewPager in xml.

values/integers contains <integer name="view_pager_rotation">0</integer>

values-ldrtl/integers contains <integer name="view_pager_rotation">180</integer>

Note that the content is also get rotated.

Update 02/11/2019

Now it's supported with viewpager2 .




回答4:


In the screenshot you gave us , not only the ViewPager is not drawing itseft RTL, nothing is already RTL. How can be that if you set in the application tag supportsRtl="true" ?? You have to set RTL in the your phone Settings under Development options. If I am not wrong you have to set nothing to support RTL automatically in ViewPager After getting your ViewPager propterly adjusted to RTL you can set which fragment you want to be the default fragment putting the following inside onCreate():

viewPager.setCurrentItem(number) 

where number indicates the number of the fragment in a zero based index. For example to select the first one, set 0, for the second set 1, and so on.




回答5:


Use this library

https://github.com/duolingo/rtl-viewpager

implementation 'com.android.support:support-core-ui:<choose_your_version>'
implementation 'com.duolingo.open:rtl-viewpager:1.0.3'



回答6:


There is another easy way to do so is by applying rotation to ViewPager and it's child view as follows:

Step 1. Change the rotation of the View pager

if(LocaleUtil.isRTL()) viewPager.setRotationY(180);

Step 2. Then again change the direction of the fragment container which is the child of ViewPager,

if(LocaleUtil.isRTL()) rootView.setRotationY(180);

In my case i had another fragment as child of view pager, so after inflating the layout i changed the direction of rootView.

LocaleUtil.java

public class LocaleUtil {

    // other functions

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

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



回答7:


After a long research I found a very simple solution. Without reverse adapters, rotation child in their classes and etc.

open class RtlViewPager : ViewPager {

    constructor(context: Context) : super(context)

    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)

    override fun onRtlPropertiesChanged(layoutDirection: Int) {
        super.onRtlPropertiesChanged(layoutDirection)
        if (layoutDirection == View.LAYOUT_DIRECTION_RTL) {
            rotationY = 180f
        }
    }

    override fun onViewAdded(child: View?) {
        if (layoutDirection == View.LAYOUT_DIRECTION_RTL) {
            child?.rotationY = 180f
        }
        super.onViewAdded(child)
    }

}



回答8:


I think you can set current page to the last page using viewPager.setCurrentItem(). Then it will swipe left to right .. :)



来源:https://stackoverflow.com/questions/37071342/how-to-create-rtl-viewpager

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!