Home » Android » android – Why do the TabLayout's tabs' icons/texts blink when swiping between pages?

android – Why do the TabLayout's tabs' icons/texts blink when swiping between pages?

Posted by: admin June 16, 2020 Leave a comment

Questions:

Background

I’ve used the PagerSlidingTabStrip library for a long time, to show tabs above a ViewPager.

Recently, I was tasked to set icons (using selectors, with selected-vs-unselected states) instead of texts for the tabs, and so I did. However, it seems that the library couldn’t handle it well, showing empty tabs sometimes, so I’ve moved to TabLayout, which is a part of the design library by Google

The problem

I’ve noticed a few solutions of how to add icons to the TabLayout, but each of them has one or more of those issues :

  1. no icons are shown
  2. icons are shown, but can blink from time to time, especially when using a selector for them with “exitFadeDuration” being set, or when swiping fast
  3. clicking on tabs does not change the current page of the viewPager.

The code

The code I’ve used is from cheesesquare sample, in the MainActivity.java file. It’s quite basic:

      final TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
      ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
      ...
      tabLayout.setupWithViewPager(viewPager);

The solutions I’ve tried are:

  1. setting an icon for each tab (and remove “getPageTitle” code of the adapter) :

    for (int i = 0; i < tabLayout.getTabCount(); i++) 
        tabLayout.getTabAt(i).setIcon(...);
    

    Also tried adding setOnTabSelectedListener for when I didn’t use a selector.

    This solution results in blinking effect (issue #2).

  2. Extending TabLayout to support icons or implementing TabViewProvider, as shown here.

    Extending TabLayout doesn’t show icons at all (issue #1), and implementing TabViewProvider has the issue of blinking icons (quite rare though).

  3. For getPageTitle, return a SpannableString that has the icon in it, as shown here . This didn’t show the icons at all for me.

I remember I tried other solutions too, but they also had issues as I’ve mentioned.

The question

What is the correct way to set icons for the tabs?

Is there an official way to achieve this? I’d like to at least have a selected&unselected images for each tab. The transition of when selecting is a good bonus, which I’ve hoped to achieve as it looks nicer this way.

Why do the icons blink anyway? I’ve noticed that it occurs even for texts…

Is there maybe a workaround?

How to&Answers:

It seems to be a known issue, and that it happens for texts too:

https://code.google.com/p/android/issues/detail?id=180454

It will get fixed on the next version of the library.

A workaround is to use previous versions, for now:

com.android.support:design:22.2.0

EDIT: this is not a good workaround, as icons can disappear on some cases (I think a combination of orientation change and swiping).

EDIT: I think that it doesn’t disappear, but more like changing its color to something else that doesn’t exist in the selector I’ve given it (which has only 2 states: selected and default).

EDIT: ok, found a workaround for the icons.

  1. use the old version (22.2.0) as I’ve mentioned above.

  2. you need to avoid using selectors for the icons. Use the exact image resource ids instead:

    private static final int[] TAB_ICONS_UNSELECTED = {...    };
    private static final int[] TAB_ICONS_SELECTED = {...    };
    
  3. update the icons based on the page selections, as such:

    mViewPager.addOnPageChangeListener(new OnPageChangeListener() {
        @Override
        public void onPageSelected(final int position) {
            for (int i = 0; i < tabLayout.getTabCount(); ++i)
                tabLayout.getTabAt(i).setIcon(i != position ? TAB_ICONS_UNSELECTED[i] : TAB_ICONS_SELECTED[i]);
        }
    });
    

Also, remember to call about the same loop when initializing the TabLayout. Something like that:

    for (int i = 0; i < tabLayout.getTabCount(); ++i)
        tabLayout.getTabAt(i).setIcon(i != mViewPager.getCurrentItem() ? TAB_ICONS_UNSELECTED[i] : TAB_ICONS_SELECTED[i]);

I think that this should also fix the issue for texts and not just icons.


EDIT: it seems that v23 will get it fixed, and that it will be available very soon.