How do I change the text style of a selected tab when using tabLayout?

后端 未结 11 2782
南笙
南笙 2021-02-19 07:57

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.

相关标签:
11条回答
  • 2021-02-19 08:31

    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
    }
    
    0 讨论(0)
  • 2021-02-19 08:41

    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)
                }
            }
        }
    })
    
    0 讨论(0)
  • 2021-02-19 08:41

    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
        }
    
    0 讨论(0)
  • 2021-02-19 08:43

    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" />
    
    0 讨论(0)
  • 2021-02-19 08:48

    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) { }
    });
    
    0 讨论(0)
  • 2021-02-19 08:49

    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)
                }
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题