Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TabLayoutMediator with smoothScroll = false, causes manual page (via swiping) to abruptly stop animating #1865

Open
stephentalley opened this issue Nov 10, 2020 · 1 comment · May be fixed by #2713 or #3918

Comments

@stephentalley
Copy link

Create a ViewPager2 and make sure isUserInputEnabled is true.

Tie the ViewPager2 to a TabLayout, ensuring that smoothScroll is false:

TabLayoutMediator(tabLayout, viewPager, true, false) { tab, position ->
    …
}.attach()

With these settings, we should expect user input (i.e. swipe) on the ViewPager2 to result in a smooth animation, while clicking on a tab should result in a non-animated (instant) change in page.

However, what actually happens is that the swipe animation abruptly stops as soon as the user lifts his/her finger.

This happens because of a circular relationship between TabLayoutMediator.ViewPagerOnTabSelectedListener and TabLayoutMediator.TabLayoutOnPageChangeCallback. The user swipe should just update the TabLayout UI and be done, but instead it triggers the TabLayoutOnPageChangeCallback, which in turn calls the ViewPagerOnTabSelectedListener, which then calls viewPager.setCurrentItem with smooth = false. That last piece aborts the animation in progress.

This a side effect of:

#813 [TabLayout] disable ViewPager2 smoothScroll with TabLayoutMediator

Note that passing smoothScroll = true is not a solution because it then causes unwanted animation after tab clicks.

Expected behavior: Swipe page animation should continue until ViewPager2 settles.

Source code: See mentioned classes in TabLayoutMediator.java.

Android API version: Any

Material Library version: 1.3.0-alpha03

Device: Any

h6ah4i added a commit to h6ah4i/material-components-android that referenced this issue May 21, 2022
@archer-n
Copy link

I'm trying to solve this problem. The solution I used was to only trigger the "ViewPager2.setCurrentItem" if "tab.getPosition()" is inconsistent with "viewPager.getCurrentItem()". It seems to work so far,Here are my modifications:

        @Override
        public void onTabSelected(@NonNull TabLayout.Tab tab) {
+            if (viewPager.getCurrentItem() != tab.getPosition()) {
                viewPager.setCurrentItem(tab.getPosition(), smoothScroll);
+            }
        }

Material Library version: 1.3.0

archer-n added a commit to archer-n/material-components-android that referenced this issue Dec 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
4 participants
@drchen @stephentalley @archer-n and others