How to create RTL ViewPager?

*爱你&永不变心* 提交于 2019-11-29 02:01:23

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.

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

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 .

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.

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'

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

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

}

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

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