How to reverse viewpager swiping
Asked Answered
H

7

6

So my app is in RTL, and with that, the tabs are now ordered from right to left..!

..But when I swipe to slide between the tabs, it contradicts the common sense, so I want to reverse it..! see the picture to see the problem..!

What I want is..! > when I'm in Tab1 and then I swipe from left to right I want it to slide to Tab 2 and so on..!

is that possible..!?

enter image description here

THE CODE


My Customer ViewPager

public class CustomViewPager extends android.support.v4.view.ViewPager{
private boolean enabled;

public CustomViewPager(Context context, AttributeSet attrs) {
    super(context, attrs);
    this.enabled = true;
}


@Override
public boolean onTouchEvent(MotionEvent event) {
    if (this.enabled) {
        return super.onTouchEvent(event);
    }

    return false;
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    if (this.enabled) {
        return super.onInterceptTouchEvent(event);
    }

    return false;
}

public void setPagingEnabled(boolean enabled) {
    this.enabled = enabled;
 }
 }

My TabActivity (Helper Class)

  public class TabbedActivity extends BaseActivity { 

 //I extend BaseActivity to avoid repeating UI code like toolbar and stuff..

protected CustomViewPager viewPager;
public OrdersAdapter adapter;
public TabLayout tabs;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    tabs.setTabGravity(TabLayout.GRAVITY_FILL);
    viewPager.setAdapter(adapter);
    viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabs));


    tabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {

        @Override
        public void onTabSelected(TabLayout.Tab tab) {
            setTabSelected(tab);
        }


        @Override
        public void onTabUnselected(TabLayout.Tab tab) {

        }

        @Override
        public void onTabReselected(TabLayout.Tab tab) {

        }
    });
  }


public void setTabSelected(TabLayout.Tab tab) {
    viewPager.setCurrentItem(tab.getPosition());
}

public void addTab(int title) {

    tabs.addTab(tabs.newTab().setText(getString(title)));

}

}

My Activity that contains the Tablayout and has three fragments, one for each tab.

public class MyOrders extends TabbedActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    setContentView(R.layout.activity_orders);

    tabs = (TabLayout) findViewById(R.id.tab_layout);
    addTab(R.string.NewOrderTabTitle); //tab1
    addTab(R.string.MyOrderTabTitle); // tab2
    addTab(R.string.FinOrderTabTitle); //tab3

     adapter = new OrdersAdapter(getSupportFragmentManager(), tabs.getTabCount());
    viewPager = (CustomViewPager) findViewById(R.id.pager);
    viewPager.setPagingEnabled(true);

    tabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
        @Override
        public void onTabSelected(TabLayout.Tab tab) {
            viewPager.setCurrentItem(tab.getPosition());

        }

        @Override
        public void onTabUnselected(TabLayout.Tab tab) {

        }

        @Override
        public void onTabReselected(TabLayout.Tab tab) {

        }
    });

    viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        }

        @Override
        public void onPageSelected(int position) {

        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    });

    super.onCreate(savedInstanceState);


 }
}

Update


@regev avraham

adding the tabs in the reverse order, and then use viewPager.setCurrentItem(adapter.getCount() - 1); to select the last tab.

based on your comment, here's what I did in the Activity that has tablayout

 //code...
 tabs = (TabLayout) findViewById(R.id.tab_layout);
    addTab(R.string.FinOrderTabTitle); //tab3
    addTab(R.string.MyOrderTabTitle); // tab2
    addTab(R.string.NewOrderTabTitle); //tab1
 //code...

 viewPager.setCurrentItem(adapter.getCount() - 1);
Haemoid answered 13/5, 2017 at 12:2 Comment(0)
M
3

This is a little tricky, the android viewPager from right to left has a little bug, only the page titles are from right to left and the pages themselves don't.

In order to fix this, what I did was using the regular left to right layout and adding the tabs in the reverse order, and then use viewPager.setCurrentItem(adapter.getCount() - 1); to select the last tab.

This is how the result should look like: https://drive.google.com/open?id=0B0FzrLgjet7pSE9lMFFFT0JiekE

where size is the first tab, the display is the second and so on

To keep RTL behavior and the LTR behavior you should use this:

Configuration config = getResources().getConfiguration();
if (config.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL)
{
     //use the RTL trick here
}
else
{
     //use the regular case here
}
Mulry answered 13/5, 2017 at 12:52 Comment(7)
I did this, but it only recorded my tabs position and didn't reversed the swipe.! can you show me what code to be changed exactly.!Haemoid
Could you please add what you have done?, This solution worked for my app.Mulry
I update my answer with a video that shows the desired behavior. Is this what you want to achieve?Mulry
YES.. that's exactly what I want, but I did what you said and it didn't work, so I'm more likely missing something, can you please check the classes above and see what should be changed and where exactly,, I really can use the help.!Haemoid
Have you forgot to set the tab layout direction to be left to right instead of right to left?Mulry
It worked, but one last problem remains...! every time the activity that holds the 3 tabs gets launched it opens tab3 by default not 1..? how can I solve that..!?Haemoid
Updated my answer.Mulry
W
5

you can check this Lib

https://github.com/diego-gomez-olvera/RtlViewPager

and implement as below

dependencies {
...
compile 'com.booking:rtlviewpager:1.0.1'
}

just add this instead of Viewpager

<com.booking.rtlviewpager.RtlViewPager
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
Willing answered 13/5, 2017 at 12:54 Comment(2)
I can't do that, I don't wanna use library for this. I was hoping to find a solution without that..!Haemoid
Thanks. Great library. Works perfectly.Preoccupy
A
4

I kind of faced this problem developing a RTL app. Here's what to do:

  1. Add tabs in reverse order :

tabLayout.addTab(tabLayout.newTab().setText("Tab2"); tabLayout.addTab(tabLayout.newTab().setText("Tab1");

  1. Customize ViewPager Adapter to return Fragments in reverse order :
public Fragment getItem(int position) {
    switch (position) {
        case 0:
            Fragment2 f2 = new Fragment2();
            return f2;
        case 1:
            Fragment1 f1 = new Fragment1();
            return f1;
        default:
            return null;
    }
}
  1. Select the last tab index at OnCreate :
TabLayout.Tab tab = tabLayout.getTabAt(1);
tab.select();
  1. Set direction of TabLayout to LTR :
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
    tabLayout.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
}
  1. And finally your onTabSelected event should looks like this :
public void onTabSelected(TabLayout.Tab tab) {
    viewPager.setCurrentItem(tab.getPosition());
}

It works well.

Alfano answered 26/11, 2018 at 11:35 Comment(0)
M
3

This is a little tricky, the android viewPager from right to left has a little bug, only the page titles are from right to left and the pages themselves don't.

In order to fix this, what I did was using the regular left to right layout and adding the tabs in the reverse order, and then use viewPager.setCurrentItem(adapter.getCount() - 1); to select the last tab.

This is how the result should look like: https://drive.google.com/open?id=0B0FzrLgjet7pSE9lMFFFT0JiekE

where size is the first tab, the display is the second and so on

To keep RTL behavior and the LTR behavior you should use this:

Configuration config = getResources().getConfiguration();
if (config.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL)
{
     //use the RTL trick here
}
else
{
     //use the regular case here
}
Mulry answered 13/5, 2017 at 12:52 Comment(7)
I did this, but it only recorded my tabs position and didn't reversed the swipe.! can you show me what code to be changed exactly.!Haemoid
Could you please add what you have done?, This solution worked for my app.Mulry
I update my answer with a video that shows the desired behavior. Is this what you want to achieve?Mulry
YES.. that's exactly what I want, but I did what you said and it didn't work, so I'm more likely missing something, can you please check the classes above and see what should be changed and where exactly,, I really can use the help.!Haemoid
Have you forgot to set the tab layout direction to be left to right instead of right to left?Mulry
It worked, but one last problem remains...! every time the activity that holds the 3 tabs gets launched it opens tab3 by default not 1..? how can I solve that..!?Haemoid
Updated my answer.Mulry
S
2

If your minSdkVersion is 17+ you can do this to the tab layout:

TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
Stgermain answered 13/5, 2017 at 12:9 Comment(1)
it didn't work, nothing changed when I added this line.!Haemoid
T
1

Now, You can do it in efficient way with a similar widget (support RTL paging-swipe). It will automatically change the swipe direction according to the system local or you can set it manually.

Android has developed a new widget named ViewPager2

ViewPager2 is an improved version of the ViewPager,it offers enhanced functionality and addresses common difficulties with using ViewPager.

You can follow these simple steps to create ViewPager2 integrated with TabLayout.

  1. in layout_main.xml use this code:

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.coordinatorlayout.widget.CoordinatorLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
     <com.google.android.material.appbar.AppBarLayout
         android:id="@+id/app_bar_layout"
         android:layout_width="match_parent"
         android:layout_height="wrap_content">
    
        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:title="@string/app_name">
        </androidx.appcompat.widget.Toolbar>
    
        <com.google.android.material.tabs.TabLayout
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/colorPrimary" />
    
    </com.google.android.material.appbar.AppBarLayout>
    
    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layoutDirection="locale"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />
    
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
    
  2. Create adapter class with name PagerAdapter:

    public class PagerAdapter extends FragmentStateAdapter {
        public PagerAdapter(FragmentActivity fm) {
            super(fm);
        }
    
        @NonNull
        @Override
        public Fragment createFragment(int position) {
            switch (position) {
                case 0:
                    return YourFragment1.newInstance();
                case 1:
                    return YourFragment2.newInstance();
            }
            return null;
        }
    
        @Override
        public int getItemCount() {
            return 2;
        }
    }
    
  3. In MainActivity (using view binding to get views from xml files):

    public class MainActivity extends AppCompatActivity {
         //Tabs titles
         private static final int[] TAB_TITLES = new int[]{R.string.tab_text_1, R.string.tab_text_2};
         //Binding object
         private ActivityMainBinding binding;
    
         @Override
         protected void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
             //Inflate layout
             binding = ActivityMainBinding.inflate(getLayoutInflater());
             View view = binding.getRoot();
             setContentView(view);
    
             //Get TabLayout View
             TabLayout tabs = binding.tabs;
             //Get the viewPager View
             ViewPager2 viewPager = binding.viewPager;
    
             //Adapter for ViewPager
             PagerAdapter pagerAdapter = new PagerAdapter(this);
             //Set Adapter for ViewPager
             viewPager.setAdapter(pagerAdapter);
    
             //Integrate TabLayout with ViewPager
             //i use it to get tabs titles
             new TabLayoutMediator(tabs, viewPager, new TabLayoutMediator.TabConfigurationStrategy() {
                 @Override
                 public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
                     //set the title for the tab at position index
                     tab.setText(getResources().getString(TAB_TITLES[position]));
                 }
             }).attach();
         }
    }
    

These resources I have used (you can read for more details):

  • Create ViewPager2 from start : this link.
  • Migrate from ViewPager to ViewPager2 : this link.

I hope I helped with this.

Trip answered 29/10, 2020 at 12:25 Comment(0)
O
0

The simplest way is using this one line of code :

tabLayout.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);

for RTL ordering of your tabs, you should do it in pager :

viewPager.setCurrentItem(adapter.getCount());

thanks to : arash-hatemi

Overrate answered 27/2, 2018 at 11:14 Comment(0)
A
0

You can set ViewPager rotationY to 180 degree and set rotationY of the child views on instantiateItem method to 180 degree.

Example:

ViewPager viewPager = new ViewPager(context);
viewPager.setRotationY(180F);
viewPagerMediaViewer.setAdapter(new PagerAdapter() {
    @Override
    public int getCount() {
        return 0;
    }

    @Override
    public Object instantiateItem(@NonNull ViewGroup container, int position) {
        LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);

        View childView = inflater.inflate(R.layout.model_view_pager_item, container, false);

        container.addView(currentView);
        childView.setRotationY(180F);
        return currentView;
    }

    @Override
    public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
        return view == object;
    }

    @Override
    public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
        container.removeView((LinearLayout)object);
    }
});
Albertalberta answered 9/12, 2021 at 19:32 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Sexed

© 2022 - 2024 — McMap. All rights reserved.