Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 466
android developer Avatar asked Aug 05 '15 09:08

android developer


People also ask

What is Tab layout in android?

In Android TabLayout is a new element introduced in Design Support library. It provides horizontal layout to display tabs on the screen. We can display more screens in a single screen using tabs. We can quickly swipe between the tabs.


1 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.

like image 152
android developer Avatar answered Oct 16 '22 10:10

android developer