307

How should I select a tab in TabLayout programmatically?

 TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
 tabLayout.setupWithViewPager(viewPager);
David Kariuki
  • 1,522
  • 1
  • 15
  • 30
Kid24
  • 4,401
  • 4
  • 23
  • 19

29 Answers29

507

If you know the index of the tab you want to select, you can do it like so:

TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
TabLayout.Tab tab = tabLayout.getTabAt(someIndex);
tab.select();

This technique works even if you're using the TabLayout by itself without a ViewPager (which is atypical, and probably bad practice, but I've seen it done).

Firefly
  • 5,425
  • 1
  • 10
  • 10
  • 12
    This solution only works if the tab has been added to the action bar, which might not allways be the case. From the documentation for `TabLayout.Tab.select()`: *"Select this tab. Only valid if the tab has been added to the action bar."* – Daniel Kvist Oct 26 '15 at 22:15
  • 8
    @DanielKvist, actually the documentation itself is incorrect. The source code speaks for itself. This answer should be the accepted answer. – Jason Sparc Feb 16 '16 at 05:53
  • @JasonSparc Hmm, I remember it not working for me when I last tried this solution, but I'll see if I can check double check how it works for me. Have you tried? It might work in some cases, while not in other cases? It might depend on API-level or something similar? – Daniel Kvist Feb 16 '16 at 06:11
  • Thanks for clearing the Air on half cooked answers! Because that just doesn't work on standalone TabLayout probably because of the reason you stated; It's meant to work with Tabs in Actionbar! – sud007 Jul 26 '16 at 12:47
  • 6
    Why using TabLayout without ViewPager should be considered bad practice ? – tomalf2 Jan 05 '17 at 22:41
  • @tomalf2 'cause user can't select tab by swiping pages to the left and right in case if you do not use view pager – Yazon2006 Apr 21 '18 at 00:10
  • Will the addOnTabSelectedListener be fired? It should be helpful in case of initialization. – Jomme Jan 15 '20 at 19:29
  • this solution worked well. Thanks for the solution. – Parmendra Singh Jun 22 '21 at 02:28
101

This is how I solved it:

void selectPage(int pageIndex){
    tabLayout.setScrollPosition(pageIndex,0f,true);
    viewPager.setCurrentItem(pageIndex);
}
dap
  • 1,011
  • 1
  • 7
  • 3
88

Use this:

tabs.getTabAt(index).select();

Keep in mind that, if currentTabIndex and index are same then this sends your flow to onTabReselected and not onTabSelected.

Atul Bhardwaj
  • 6,647
  • 5
  • 45
  • 63
Riyas PK
  • 3,147
  • 1
  • 23
  • 29
42

Use this:

<android.support.design.widget.TabLayout
    android:id="@+id/patienthomescreen_tabs"
    android:layout_width="match_parent"
    android:layout_height="72sp"
    app:tabGravity="fill"
    app:tabMode="fixed"
    app:tabIndicatorColor="@android:color/white"
    app:tabSelectedTextColor="@color/green"/>

After in OnClickListener:

TabLayout tabLayout = (TabLayout) findViewById(R.id.patienthomescreen_tabs);
TabLayout.Tab tab = tabLayout.getTabAt(someIndex);
tab.select();

Keep in mind that, if currentTabIndex and index are same then this sends your flow to onTabReselected and not onTabSelected.

Atul Bhardwaj
  • 6,647
  • 5
  • 45
  • 63
Pravin Suthar
  • 1,403
  • 1
  • 14
  • 25
27

This is probably not the ultimate solution, and it requires that you use the TabLayout together with a ViewPager, but this is how I solved it:

void selectPage(int pageIndex)
{
    viewPager.setCurrentItem(pageIndex);
    tabLayout.setupWithViewPager(viewPager);
}

I tested how big the performance impact of using this code is by first looking at the CPU- and memory monitors in Android Studio while running the method, then comparing it to the load that was put on the CPU and memory when I navigated between the pages myself (using swipe gestures), and the difference isn't significantly big, so at least it's not a horrible solution...

Hope this helps someone!

Daniel Kvist
  • 3,032
  • 5
  • 26
  • 51
  • 1
    When I did dap's solution (`tabLayout.setScrollPosition(pageIndex,0f,true);`), when I clicked on the tab to the right, it didn't update the ViewPager's page (I don't know why). Only clicking back on the left tab & then on the right tab again would finally update the page to have the right tab's page, which is very glitchy. But this solution had no glitches. – Rock Lee Jun 02 '16 at 22:33
15

Just set viewPager.setCurrentItem(index) and the associated TabLayout would select the respective tab.

Panduka DeSilva
  • 817
  • 9
  • 12
15

With the TabLayout provided by the Material Components Library just use the selectTab method:

TabLayout tabLayout = findViewById(R.id.tab_layout);
tabLayout.selectTab(tabLayout.getTabAt(index));

enter image description here

It requires version 1.1.0.

Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
13

If you can't use tab.select() and you don't want to use a ViewPager, you can still programmatically select a tab. If you're using a custom view through TabLayout.Tab setCustomView(android.view.View view) it is simpler. Here's how to do it both ways.

// if you've set a custom view
void updateTabSelection(int position) {
    // get the position of the currently selected tab and set selected to false
    mTabLayout.getTabAt(mTabLayout.getSelectedTabPosition()).getCustomView().setSelected(false);
    // set selected to true on the desired tab
    mTabLayout.getTabAt(position).getCustomView().setSelected(true);
    // move the selection indicator
    mTabLayout.setScrollPosition(position, 0, true);

    // ... your logic to swap out your fragments
}

If you aren't using a custom view then you can do it like this

// if you are not using a custom view
void updateTabSelection(int position) {
    // get a reference to the tabs container view
    LinearLayout ll = (LinearLayout) mTabLayout.getChildAt(0);
    // get the child view at the position of the currently selected tab and set selected to false
    ll.getChildAt(mTabLayout.getSelectedTabPosition()).setSelected(false);
    // get the child view at the new selected position and set selected to true
    ll.getChildAt(position).setSelected(true);
    // move the selection indicator
    mTabLayout.setScrollPosition(position, 0, true);

    // ... your logic to swap out your fragments
}

Use a StateListDrawable to toggle between selected and unselected drawables or something similar to do what you want with colors and/or drawables.

kenodoggy
  • 1,359
  • 14
  • 8
12

A bit late but might be a useful solution. I am using my TabLayout directly in my Fragment and trying to select a tab quite early in the Fragment's Lifecycle. What worked for me was to wait until the TabLayout finished drawing its child views by using android.view.View#post method. i.e:

int myPosition = 0;
myFilterTabLayout.post(() -> { filterTabLayout.getTabAt(myPosition).select(); });
ahmed_khan_89
  • 2,755
  • 26
  • 49
  • 2
    correct answer worked for me but some delay will give it nice effect `new Handler().postDelayed(()->{ tabLayout.post(() -> { tabLayout.getTabAt(myPosition).select(); }); },200);` – Hisham Nov 21 '18 at 18:55
  • @Hisham, I'm not fan of delay-hook in coding ..Unfortunately this is the only safe way to do so. mainly with Pager2.. – Maher Abuthraa Jan 10 '22 at 01:03
  • i do not recommend using this `Handler.postDelayed` solution, because it may lead to NPE if the user quits the screen very quickly: it could be that after the delay of 200 your `tabLayout` is not there anymore... – ahmed_khan_89 May 13 '23 at 09:43
9

You can try solving it with this:

TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);

TabLayout.Tab tab = tabLayout.getTabAt(pos);
if (tab != null) {
    tab.select();
}
grine4ka
  • 2,878
  • 1
  • 19
  • 29
CoCo Dev
  • 306
  • 4
  • 6
8

Newest simple solution worked for me:

with(binding.tablayout) {
    selectTab(getTabAt(tabPosisiton))
}

with tabPosition start from 0

KiluSs
  • 421
  • 4
  • 13
6

try this

    new Handler().postDelayed(
            new Runnable(){
                @Override
                public void run() {
                    if (i == 1){
                        tabLayout.getTabAt(0).select();
                    } else if (i == 2){
                        tabLayout.getTabAt(1).select();
                    }
                }
            }, 100);
Thamays
  • 2,978
  • 26
  • 31
  • Thanks.it worked for me. But is it good practice to to use delayed? – Harsh Shah Nov 17 '16 at 05:44
  • I guess it is bad to run thread on any of the layout cause if suppose you are fetching the text for tab from the backend server and if b'coz of any reason the server delays then this system thread will unneseccarily consume your device resources. – cammando Mar 06 '17 at 06:19
  • so ugly solution – Lester Aug 22 '17 at 10:32
  • This doesn't work for me. How do I make it that if the user clicks a tab, then delay that tab selection? I can't get anything to work. I tried instead if i ==1 to use (mViewPager.getCurrentItem()==0) but it doesn't work and neither does anything else. – iBEK Dec 10 '17 at 02:00
5

Kotlin Users:

Handler(Looper.getMainLooper()).postDelayed(
            { tabLayout.getTabAt(position).select() }, 100
        )

This will also scroll your tab layout in case if it needs to scroll.

Kishan Solanki
  • 13,761
  • 4
  • 85
  • 82
3

A combined solution from different answers is:

new Handler().postDelayed(() -> {
  myViewPager.setCurrentItem(position, true);
  myTabLayout.setScrollPosition(position, 0f, true);
},
100);
Zon
  • 18,610
  • 7
  • 91
  • 99
3

you should use a viewPager to use viewPager.setCurrentItem()

 viewPager.setCurrentItem(n);
 tabLayout.setOnTabSelectedListener(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) {

            }
        });
Luis Muñoz
  • 139
  • 1
  • 4
2

I am using TabLayout to switch fragments. It works for the most part, except whenever I tried to select a tab programmatically using tab.select(), my TabLayout.OnTabSelectedListener would trigger the onTabSelected(TabLayout.Tab tab), which would cause me much grief. I was looking for a way to do programmatic selection without triggering the listener.

So I adapted @kenodoggy 's answer to my use. I was further facing a problem where some of the internal objects would return null (because they weren't created yet, because I was answering onActivityResult() from my fragment, which occurs before onCreate() in the case the activity is singleTask or singleInstance) so I wrote up a detailed if/else sequence which would report the error and fall through without the NullPointerException that would otherwise trigger. I use Timber for logging, if you're not using that substitute with Log.e().

void updateSelectedTabTo(int position) {
    if (tabLayout != null){
        int selected = tabLayout.getSelectedTabPosition();
        if (selected != -1){
            TabLayout.Tab oldTab = tabLayout.getTabAt(0);
            if (oldTab != null){
                View view = oldTab.getCustomView();
                if (view != null){
                    view.setSelected(false);
                }
                else {
                    Timber.e("oldTab customView is null");
                }
            }
            else {
                Timber.e("oldTab is null");
            }
        }
        else {
            Timber.e("selected is -1");
        }
        TabLayout.Tab newTab = tabLayout.getTabAt(position);
        if (newTab != null){
            View view = newTab.getCustomView();
            if (view != null){
                view.setSelected(false);
            }
            else {
                Timber.e("newTab customView is null");
            }
        }
        else {
            Timber.e("newTab is null");
        }
    }
    else {
        Timber.e("tablayout is null");
    }
}

Here, tabLayout is my memory variable bound to the TabLayout object in my XML. And I don't use the scrolling tab feature so I removed that as well.

Dhiraj Gupta
  • 9,704
  • 8
  • 49
  • 54
2

If you are using TabLayout with viewPager then this helps you. You set the TabLayout with ViewPager in addOnpagelistener.

if you want to set the TabLayout position directly(not click on the Tab individual) try below code tabLayout.getTabAt(position_you_want_to_set).select()

   /* will be invoked whenever the page changes or is incrementally scrolled*/
    viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

        }

        @Override
        public void onPageSelected(int position) {
            tabLayout.getTabAt(position).select();
        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    });
Sniffer
  • 1,495
  • 2
  • 14
  • 30
  • 1
    Welcome to StackOverflow! While the answer may be correct, you should explain what the code provided does to solve the issues declared – xKobalt Jul 29 '20 at 07:15
2

This won't work for app that has ViewPager2 Implemented, For that, you need to use

viewPager2.setCurrentItem(position);

inside onConfigureTab, onConfigureTab if found when we use TabLayoutMediator

i.e

TabLayoutMediator tabLayoutMediator = new TabLayoutMediator(
                tabLayout, viewPager2, new TabLayoutMediator.TabConfigurationStrategy() {
            @Override
            public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
                switch (position){
                    case 0 : tab.setIcon(getResources().getDrawable(R.drawable.camera));
                            break;
                    case 1 : tab.setText("CHAT");
                            viewPager2.setCurrentItem(position); // when app starts this will be the selected tab
                            break;
                    case 2 : tab.setText("STATUS");
                            break;
                    case 3 : tab.setText("CALL");
                        break;
                }
            }
        }
        );
        tabLayoutMediator.attach();
Swapnil Padaya
  • 687
  • 5
  • 14
1

add for your viewpager:

 viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {

            @Override
            public void onPageSelected(int position) {
                array.clear();
                switch (position) {
                    case 1:
                        //like a example
                        setViewPagerByIndex(0);
                        break;
                }
            }

            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            }

            @Override
            public void onPageScrollStateChanged(int state) {
            }
        });

//on handler to prevent crash outofmemory

private void setViewPagerByIndex(final int index){
    Application.getInstance().getHandler().post(new Runnable() {
        @Override
        public void run() {
            viewPager.setCurrentItem(index);
        }
    });
}
Alex Zaraos
  • 6,443
  • 2
  • 26
  • 21
0

By default if you select a tab it will be highlighted. If you want to select Explicitly means use the given commented code under onTabSelected(TabLayout.Tab tab) with your specified tab index position. This code will explains about change fragment on tab selected position using viewpager.

public class GalleryFragment extends Fragment implements TabLayout.OnTabSelectedListener 
{
private ViewPager viewPager;public ViewPagerAdapter adapter;private TabLayout tabLayout;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_gallery, container, false);
viewPager = (ViewPager) rootView.findViewById(R.id.viewpager);
adapter = new ViewPagerAdapter(getChildFragmentManager());
adapter.addFragment(new PaymentCardFragment(), "PAYMENT CARDS");
adapter.addFragment(new LoyaltyCardFragment(), "LOYALTY CARDS");
viewPager.setAdapter(adapter);
tabLayout = (TabLayout) rootView.findViewById(R.id.tabs);
    tabLayout.setupWithViewPager(viewPager);
    tabLayout.setOnTabSelectedListener(this);
}

@Override
public void onTabSelected(TabLayout.Tab tab) {
    //This will be called 2nd when you select a tab or swipe using viewpager
    final int position = tab.getPosition();
    Log.i("card", "Tablayout pos: " + position);
    //TabLayout.Tab tabdata=tabLayout.getTabAt(position);
    //tabdata.select();
    tabLayout.post(new Runnable() {
        @Override
        public void run() {
            if (position == 0) {
                PaymentCardFragment paymentCardFragment = getPaymentCardFragment();
                if (paymentCardFragment != null) {
                   VerticalViewpager vp = paymentCardFragment.mypager;
                    if(vp!=null)
                    {
                      //vp.setCurrentItem(position,true);
                      vp.setCurrentItem(vp.getAdapter().getCount()-1,true);
                    }
                  }
            }
            if (position == 1) {
               LoyaltyCardFragment loyaltyCardFragment = getLoyaltyCardFragment();
                if (loyaltyCardFragment != null) {
                   VerticalViewpager vp = loyaltyCardFragment.mypager;
                    if(vp!=null)
                    {
                        vp.setCurrentItem(position);
                    }
                  }
            }
        }
    });
}

@Override
public void onTabUnselected(TabLayout.Tab tab) {
 //This will be called 1st when you select a tab or swipe using viewpager
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
  //This will be called only when you select the already selected tab(Ex: selecting 3rd tab again and again)
}
 private PaymentCardFragment getLoyaltyCardFragment() {
    Fragment f = adapter.mFragmentList.get(viewPager.getCurrentItem());

   if(f instanceof PaymentCardFragment)
   {
    return (PaymentCardFragment) f;
   }
   return null;
 }
private LoyaltyCardFragment getPaymentCardFragment() {
    Fragment f = adapter.mFragmentList.get(viewPager.getCurrentItem());
    if(f instanceof LoyaltyCardFragment)
   {
    return (LoyaltyCardFragment) f;
   }
   return null;
 }
  class ViewPagerAdapter extends FragmentPagerAdapter {
   public List<Fragment> mFragmentList = new ArrayList<>();
    private final List<String> mFragmentTitleList = new ArrayList<>();
   public void addFragment(Fragment fragment, String title) {
   mFragmentList.add(fragment);
   mFragmentTitleList.add(title);
  }
 }
}
anand krish
  • 4,281
  • 4
  • 44
  • 47
0

This can help too

viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
    @Override
    public void onPageScrolled(int i, float v, int i1) {
    }

    @Override
    public void onPageSelected(int i) {
        tablayout.getTabAt(i).select();
    }

    @Override
    public void onPageScrollStateChanged(int i) {
    }
});
grine4ka
  • 2,878
  • 1
  • 19
  • 29
Hadi Note
  • 1,386
  • 17
  • 16
0

You can set TabLayout position using following functions

public void setTab(){
 tabLayout.setScrollPosition(YOUR_SCROLL_INDEX,0,true);
 tabLayout.setSelected(true);
}
0

If it so happens that your default tab is the first one(0) and you happen to switch to a fragment, then you must manually replace the fragment for the first time. This is because the tab is selected before the listener gets registered.

private TabLayout mTabLayout;

...

@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_tablayout, container, false);
    mTabLayout = view.findViewById(R.id.sliding_tabs);
    mTabLayout.addOnTabSelectedListener(mOnTabSelectedListener);

    getActivity().getSupportFragmentManager().beginTransaction()
        .replace(R.id.tabContent, MyFirstFragment.newInstance()).commit();
    return view;
}

Alternatively, you can consider calling getTabAt(0).select() and overriding onTabReselected like so:

@Override
public void onTabReselected(TabLayout.Tab tab) {
    // Replace the corresponding tab fragment.
}

This would work because you are essentially replacing the fragment on every tab reselect.

farthVader
  • 888
  • 11
  • 19
0

If you have trouble understanding, this code can help you

private void MyTabLayout(){
    TabLayout.Tab myTab = myTabLayout.newTab(); // create a new tab
    myTabLayout.addTab(myTab); // add my new tab to myTabLayout
    myTab.setText("new tab"); 
    myTab.select(); // select the new tab
}

You can also add this to your code:

myTabLayout.setTabTextColors(getColor(R.color.colorNormalTab),getColor(R.color.colorSelectedTab));
Paul Chu
  • 1,249
  • 3
  • 19
  • 27
M3TALzero1
  • 104
  • 9
0

Try this way.

tabLayout.setTabTextColors(getResources().getColor(R.color.colorHintTextLight),
                           getResources().getColor(R.color.colorPrimaryTextLight));
Pang
  • 9,564
  • 146
  • 81
  • 122
Anandharaj R
  • 169
  • 1
  • 6
0

if u are using TabLayout without viewPager this helps

 mTitles = getResources().getStringArray(R.array.tabItems);
    mIcons = getResources().obtainTypedArray(R.array.tabIcons);
    for (int i = 0; i < mTitles.length; i++) {

        tabs.addTab(tabs.newTab().setText(mTitles[i]).setIcon(mIcons.getDrawable(i)));
        if (i == 0) {
            /*For setting selected position 0 at start*/
            Objects.requireNonNull(Objects.requireNonNull(tabs.getTabAt(i)).getIcon()).setColorFilter(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimary), PorterDuff.Mode.SRC_IN);
        }
    }

    tabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
        @Override
        public void onTabSelected(TabLayout.Tab tab) {
            Objects.requireNonNull(tab.getIcon()).setColorFilter(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimary), PorterDuff.Mode.SRC_IN);
        }

        @Override
        public void onTabUnselected(TabLayout.Tab tab) {
            Objects.requireNonNull(tab.getIcon()).setColorFilter(ContextCompat.getColor(getApplicationContext(), R.color.white), PorterDuff.Mode.SRC_IN);
        }

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

        }
    });
Tijo Thomas
  • 166
  • 1
  • 2
  • 10
0

Kotlin fix

viewPager.currentItem = 0

tabs.setupWithViewPager(viewPager)

Juan Ocampo
  • 111
  • 1
  • 3
0
TabLayout jobTabs = v.findViewById(R.id.jobTabs);
ViewPager jobFrame = v.findViewById(R.id.jobPager);
jobFrame.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(jobTabs));

this will select tab as view pager swipe page

Rachit Vohera
  • 707
  • 7
  • 10
-1

With Viewpager2, Kotlin none of the other answers helped, only this worked below. position is from fragment result listener in my case:

TabLayoutMediator(binding.tabLayout, binding.viewPager2) { _, _ ->
    binding.viewPager2 = position
}.attach()
grabz
  • 69
  • 6