I am trying to create a tab layout for my program. There are two tabs. If I try to switch to Tab2 instead of staying on Tab2, it changes back to Tab1. I have 0 clue what is causing this problem.
Here is my code
MainActivity:
tabLayout = findViewById(R.id.tablayout);
viewPager2 = findViewById(R.id.viewpager);
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentAdapter = new CustomAdapter(fragmentManager, getLifecycle());
viewPager2.setAdapter(fragmentAdapter);
tabLayout.addTab(tabLayout.newTab().setText("Tab1"));
tabLayout.addTab(tabLayout.newTab().setText("Tab2"));
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager2.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageScrollStateChanged(int state) {
tabLayout.selectTab(tabLayout.getTabAt(state));
}
});
CustomAdapter:
public class CustomAdapter extends FragmentStateAdapter {
public CustomAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle) {
super(fragmentManager, lifecycle);
}
@NonNull
@Override
public Fragment createFragment(int position) {
if(position == 1) return new BlankFragment1();
return new BlankFragment2();
}
@Override
public int getItemCount() {
return 2;
}
CodePudding user response:
Following the official docs here you can use a TabLayoutMediator
to link the tab layout and pager instead of doing it with your own listeners.
However, the root of the problem you observed is that state
in onPageScrollStateChanged
is not the position that it scrolled to - it is an integer representing the scroll state. Since SCROLL_STATE_IDLE
is 0, and SCROLL_STATE_DRAGGING
is 1, as soon as you stopped dragging it would snap back to tab 0.
Using TabLayoutMediator (recommended)
To use the TabLayoutMediator replace your addOnTabSelectedListener
, registerOnPageChangeCallback
, and manually setting the tabs (addTab
) with this, which links the tabs to the view pager and provides a method to set the tab titles
// remove the "addTab" calls, "addOnTabSelectedListener",
// and "registerOnPageChangeCallback"
new TabLayoutMediator(tabLayout, viewPager2,
(tab, position) -> tab.setText("Tab" (position 1))
).attach();
Using your own listeners
It is still possible to use your own listeners, but you have to change the view pager listener to use onPageSelected
instead of onPageScrollStateChanged
, like this:
viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
tabLayout.selectTab(tabLayout.getTabAt(position));
}
});
Note: The positions are 0-based, so you are showing "BlankFragment2" in position 0 and "BlankFragment1" in position 1 (not sure if that is what you intended).