25

I want to make the text of a selected tab bold. How can I do this either through xml or java code, whatever is easier.

Felipe Calderon
  • 675
  • 2
  • 7
  • 17

13 Answers13

33

I changed the answer suggested above a bit and it works great for me, no additional .xml files needed, hope it will help.

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

    TabLayout.Tab tab = tabLayout.getTabAt(i);
    if (tab != null) {

        TextView tabTextView = new TextView(this);
        tab.setCustomView(tabTextView);

        tabTextView.getLayoutParams().width = ViewGroup.LayoutParams.WRAP_CONTENT;
        tabTextView.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;

        tabTextView.setText(tab.getText());

        // First tab is the selected tab, so if i==0 then set BOLD typeface
        if (i == 0) {
            tabTextView.setTypeface(null, Typeface.BOLD);
        }

    }

}

tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {

    @Override
    public void onTabSelected(TabLayout.Tab tab) {
        viewPager.setCurrentItem(tab.getPosition());

        TextView text = (TextView) tab.getCustomView();

        text.setTypeface(null, Typeface.BOLD);
    }

    @Override
    public void onTabUnselected(TabLayout.Tab tab) {
        TextView text = (TextView) tab.getCustomView();

        text.setTypeface(null, Typeface.NORMAL);
    }

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

    }

});
user1974368
  • 474
  • 5
  • 13
  • ```setOnTabSelectedListener``` is deprecated. Use ```addOnTabSelectedListener``` instead. – Ivan Mar 13 '20 at 21:56
  • `.setTypeFace(null, .. )` will remove the initialised font. Use `Typeface typeface = ResourcesCompat.getFont(this, R.font.your_font);` if you want to use a specific font. – Sven van Zoelen Sep 29 '20 at 13:45
28

If you use default TabLayout (not customView), you can get TextView of tab by using getChildAt() method.

.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
        @Override
        public void onTabSelected(TabLayout.Tab tab) {
            LinearLayout tabLayout = (LinearLayout)((ViewGroup) mMainTabs.getChildAt(0)).getChildAt(tab.getPosition());
            TextView tabTextView = (TextView) tabLayout.getChildAt(1);
            tabTextView.setTypeface(tabTextView.getTypeface(), Typeface.BOLD);
        }

        @Override
        public void onTabUnselected(TabLayout.Tab tab) {
            LinearLayout tabLayout = (LinearLayout)((ViewGroup) mMainTabs.getChildAt(0)).getChildAt(tab.getPosition());
            TextView tabTextView = (TextView) tabLayout.getChildAt(1);
            tabTextView.setTypeface(null, Typeface.NORMAL);
        }

        @Override
        public void onTabReselected(TabLayout.Tab tab) { }
    });
Harvi Sirja
  • 2,472
  • 2
  • 18
  • 19
hoi
  • 2,168
  • 20
  • 22
7

I know this is an old question, but I came up with a nicer solution: I created this OnTabSelectedListener

class OnTabSelectedBoldListener : TabLayout.OnTabSelectedListener {
    override fun onTabReselected(tab: TabLayout.Tab) {}

    override fun onTabUnselected(tab: TabLayout.Tab) {
        val views = arrayListOf<View>()
        tab.view.findViewsWithText(views, tab.text, View.FIND_VIEWS_WITH_TEXT)
        views.forEach { view ->
            if (view is TextView) {
                TextViewCompat.setTextAppearance(view, R.style.TabTextAppearance)
            }
        }
    }

    override fun onTabSelected(tab: TabLayout.Tab) {
        val views = arrayListOf<View>()
        tab.view.findViewsWithText(views, tab.text, View.FIND_VIEWS_WITH_TEXT)
        views.forEach { view ->
            if (view is TextView) {
                TextViewCompat.setTextAppearance(view, R.style.TabTextAppearance_Selected)
            }
        }
    }
}
Lucas
  • 71
  • 1
  • 4
3

There is a way to add bold programmatically by using a Tab CustomView, loading a TextView into that CustomView and applying styling on the TextView:

private TabLayout mTabLayout;
protected void onCreate(Bundle savedInstanceState) {
    ...
    mTabLayout = (TabLayout) findViewById(R.id.tablayout);
    mTabLayout.setOnTabSelectedListener(new OnTabSelectedListener());
    int tabCount = mTabLayout.getTabCount();
    for (int i = 0; i < tabCount; i++) {
        TabLayout.Tab tab = mTabLayout.getTabAt(i);
        if (tab != null) {
            TextView tabTextView =
                (TextView) LayoutInflater.from(this).inflate(R.layout.tab_item, mTabLayout, false);
            tabTextView.setText(tab.getText());
            // First tab is the selected tab, so if i==0 then set Tabs_Selected style
            tabTextView.setTextAppearance(getAppContext(), i == 0 ? R.style.TextAppearance_Tabs_Selected
                                              : R.style.TextAppearance_Tabs);
            tab.setCustomView(tabTextView);
        }
    }
}
class OnTabSelectedListener implements TabLayout.OnTabSelectedListener {

    public void onTabSelected(TabLayout.Tab selectedTab) {
        int tabCount = mTabLayout.getTabCount();
        for (int i = 0; i < tabCount; i++) {
            TabLayout.Tab tab = mTabLayout.getTabAt(i);
            View tabView = tab != null ? tab.getCustomView() : null;
            if (tabView instanceof TextView) {
                ((TextView) tabView).setTextAppearance(getAppContext(), selectedTab.equals(tab)
                                                           ? R.style.TextAppearance_Tabs_Selected
                                                           : R.style.TextAppearance_Tabs);
            }
        }
    }

    @Override
    public void onTabUnselected(TabLayout.Tab tab) {
    }

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

And here is the entries in styles.xml:

<style name="TextAppearance.Tabs" parent="TextAppearance.Design.Tab">
    <item name="android:textSize">12sp</item>
    <item name="android:textColor">@android:color/white</item>
</style>

<style name="TextAppearance.Tabs.Selected">
    <item name="android:textStyle">bold</item>
</style>

And here is the layout tab_item:

<?xml version="1.0" encoding="utf-8"?>
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/tab_textview"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    tools:text="Tab 1" />
Jason Grife
  • 1,197
  • 11
  • 14
2

This is a Kotlin code for this solution

 for (i in 0..tabLayout.tabCount){
        val tab:TabLayout.Tab? = tabLayout.getTabAt(i)
        if (tab != null){
            val tabTextView:TextView = TextView(this)
            tab.customView = tabTextView

            tabTextView.layoutParams.width = ViewGroup.LayoutParams.WRAP_CONTENT
            tabTextView.layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT

            tabTextView.text = tab.text

            if (i == 0){
                // This set the font style of the first tab
                tabTextView.setTypeface(null,BOLD)
                
            }
            if (i == 1){
                // This set the font style of the first tab

                tabTextView.setTypeface(null,NORMAL)
                
            }
        }
    }
    tabLayout!!.addOnTabSelectedListener(object: TabLayout.OnTabSelectedListener {
        override fun onTabSelected(tab: TabLayout.Tab?) {
            viewPager.currentItem = tab!!.position

            val text:TextView = tab.customView as TextView

            
            text.setTypeface(null,BOLD)
            


        }

        override fun onTabUnselected(tab: TabLayout.Tab?) {
            val text:TextView = tab?.customView as TextView


            text.setTypeface(null,NORMAL)
            

        }

        override fun onTabReselected(tab: TabLayout.Tab?) {

        }

    })
Kenny
  • 31
  • 4
2

In my case, setTypeface doesn't work right after tab init so I need to use post method to wait TextView laid out then setTypeface

tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
    override fun onTabReselected(tab: TabLayout.Tab?) {
    }

    override fun onTabUnselected(tab: TabLayout.Tab?) {
        tab?.let {
            setStyleForTab(it, Typeface.NORMAL)
        }
    }

    override fun onTabSelected(tab: TabLayout.Tab?) {
        tab?.let {
            setStyleForTab(it, Typeface.BOLD)
        }
    }

    fun setStyleForTab(tab: TabLayout.Tab, style: Int) {
        tab.view.children.find { it is TextView }?.let { tv ->
            (tv as TextView).post {
                tv.setTypeface(null, style)
            }
        }
    }
})
Linh
  • 57,942
  • 23
  • 262
  • 279
1

I applied hoi's answer which is written above for default TabLayout with no custom view. It worked the best for me. But what I actually needed was to change the font family of the text inside the TabItem to a bolder one when a tab was selected. So following hoi's solution, I changed the code a bit to work for me. I am leaving this answer just in case if someone is trying to achieve something similar:

private fun addOnTabSelectedListener() {
        tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
            override fun onTabReselected(tab: TabLayout.Tab?) {
                return
            }

            override fun onTabUnselected(tab: TabLayout.Tab?) {
                tab?.position?.let {
                    changeSelectedTabItemFontFamily(it, R.font.quicksand_medium)
                }
            }

            override fun onTabSelected(tab: TabLayout.Tab?) {
                tab?.position?.let {
                    changeSelectedTabItemFontFamily(it, R.font.quicksand_bold)
                }
            }
        })
    }

private fun changeSelectedTabItemFontFamily(tabPosition: Int, @FontRes fontFamilyRes: Int) {
        val linearLayout = (this.tabLayout.getChildAt(0) as ViewGroup).getChildAt(tabPosition) as LinearLayout
        val tabTextView = linearLayout.getChildAt(1) as TextView
        val typeface = ResourcesCompat.getFont(context, fontFamilyRes)
        tabTextView.typeface = typeface
}
Şevval
  • 86
  • 1
  • 7
1

For me problem with above solutions was that reset to Typeface.NORMAL with

SetTypeface(null, Typeface.NORMAL);

wouldn't reset my typeface on default typeface for my tabs. So I had to save default typeface before it was changed in order to reset Typeface to defaultTypeface once when tab is deselected.

private TabLayout _tabLayout;

public override void OnViewCreated(View view, Bundle savedInstanceState)
{
    _tabLayout = view.FindViewById<TabLayout>(Resource.Id.my_tab_layout);
    _tabLayout.TabSelected += TabLayout_TabSelected;
    _tabLayout.TabUnselected += TabLayout_TabUnselected;
}

private void TabLayout_TabSelected(object sender, TabLayout.TabSelectedEventArgs e)
{
    SetTabTypeface(e.Tab, true);
}

private void TabLayout_TabUnselected(object sender, TabLayout.TabUnselectedEventArgs e)
{
    SetTabTypeface(e.Tab, false);
}

Typeface _defaultTypeface;

private void SetTabTypeface(TabLayout.Tab tab, bool isSelected)
{
    LinearLayout tabLinLayout = (LinearLayout)((ViewGroup)_tabLayout.GetChildAt(0)).GetChildAt(tab.Position);
    TextView tabTextView = (TextView)tabLinLayout.GetChildAt(1);

    if (_defaultTypeface == null)
        _defaultTypeface = tabTextView.Typeface;

    if (isSelected)
        tabTextView.SetTypeface(tabTextView.Typeface, TypefaceStyle.Bold);
    else
        tabTextView.SetTypeface(_defaultTypeface, TypefaceStyle.Normal);
}
ozapa
  • 281
  • 4
  • 16
0
       tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
        @Override
        public void onTabSelected(TabLayout.Tab tab) {
            tab.getCustomView().setBackgroundDrawable(getResources().getDrawable(R.mipmap.account_active));
          if (tab.getPosition()==0){
              tab.getCustomView().setBackgroundDrawable(getResources().getDrawable(R.mipmap.booking_active));
          }
          if(tab.getPosition()==1){
              tab.getCustomView().setBackgroundDrawable(getResources().getDrawable(R.mipmap.account_active));
          }
        }

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

            if (tab.getPosition()==0){
                tab.getCustomView().setBackgroundDrawable(getResources().getDrawable(R.mipmap.booking_deacive));
            }
            if(tab.getPosition()==1){
                tab.getCustomView().setBackgroundDrawable(getResources().getDrawable(R.mipmap.account_deactive));
            }
        }

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

            if (tab.getPosition()==0){
                tab.getCustomView().setBackgroundDrawable(getResources().getDrawable(R.mipmap.booking_active));
            }
            if(tab.getPosition()==1){
                tab.getCustomView().setBackgroundDrawable(getResources().getDrawable(R.mipmap.account_active));
            }
        }
    });

    setupTabIcons();
0

Hello Friends Try This

first add this method

  private void updateCounter() {
    try {
        for (int i = 0; i < tabLayout.getTabCount(); i++) {
            updateTab(tabLayout.getTabAt(i));
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

second add this Method

   private void updateTab(TabLayout.Tab tab) {
    Method method;
    try {
        method = TabLayout.Tab.class.getDeclaredMethod("getCustomView");
        method.setAccessible(true);

        View tabView = (View) method.invoke(tab, new Object[0]);

        TextView tv_title = null;

        if (tabView != null) {
            tv_title = tabView.findViewById(R.id.tv_title);
        }

        switch (tab.getPosition()) {
            case 0:
                if (tv_title != null) {
                    tv_title.setText(tabTitle[0]);

                    if(viewPager.getCurrentItem() == 0){
                        tv_title.setTypeface(CustomerApplication.getInstance().getMontserratBold());
                    }else{
                        tv_title.setTypeface(CustomerApplication.getInstance().getMontserratMedium());
                    }
                }
                break;

            case 1:
                if (tv_title != null) {
                    tv_title.setText(tabTitle[1]);

                    if(viewPager.getCurrentItem() == 1){
                        tv_title.setTypeface(CustomerApplication.getInstance().getMontserratBold());
                    }else{
                        tv_title.setTypeface(CustomerApplication.getInstance().getMontserratMedium());
                    }
                }
                break;
        }
        tab.setCustomView(tabView);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

last call view pager change listener

private final ViewPager.OnPageChangeListener onPageChangeListener = new ViewPager.OnPageChangeListener() {
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {
        updateCounter();
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }
};
Rahul Patil
  • 129
  • 1
  • 5
0

This works in JAVA

tabs.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
    @Override
    public void onTabSelected(TabLayout.Tab tab) {
        initTabSelection(tab);

        for(int index = 0; index < ((ViewGroup) tab.view).getChildCount(); index++) {
            View nextChild = ((ViewGroup) tab.view).getChildAt(index);
            if (nextChild instanceof TextView) {
                TextView v = (TextView) nextChild;
                v.setTypeface(null, Typeface.BOLD);
            }
        }
    }

    @Override
    public void onTabUnselected(TabLayout.Tab tab) {
        for(int index = 0; index < ((ViewGroup) tab.view).getChildCount(); index++) {
            View nextChild = ((ViewGroup) tab.view).getChildAt(index);
            if (nextChild instanceof TextView) {
                TextView v = (TextView) nextChild;
                v.setTypeface(null, Typeface.NORMAL);
            }
        }
    }

    @Override
    public void onTabReselected(TabLayout.Tab tab) { }
});
Marlon
  • 1,839
  • 2
  • 19
  • 42
0

You can use this on your tablayout

app:tabSelectedTextAppearance="@style/TabSelected"

the style can be like:

<style name="TabSelected">
    <item name="textAllCaps">false</item>
    <item name="fontFamily">Whatever bold font you want to use</item>
</style>
-1

In addition to previous answers, bear in mind that when modifying the style of the text in the onTabUnselected you may have to recalculate the width of the view if it was set on WRAP_CONTENT

    @Override
    public void onTabSelected(TabLayout.Tab tab) {
            TextView text = (TextView) tab.getCustomView();
            text.setTypeface(null, Typeface.BOLD); 
            text.getCustomView().measure(WRAP_CONTENT, WRAP_CONTENT)
            text.getCustomView().layoutParams.height = measuredHeight
            text.getCustomView().layoutParams.width = measuredWidth
    }
Pol
  • 181
  • 2
  • 10