如何在使用tabLayout时更改所选选项卡的文本样式?

25
我想使所选选项卡的文本加粗。我应该如何通过xml或java代码实现,哪种方法更容易,请提供建议。
13个回答

33

我稍微修改了上面建议的答案,对我来说运行得很好,不需要其他的 .xml 文件,希望它能帮到你。

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) {

    }

});

setOnTabSelectedListener已被弃用,请使用addOnTabSelectedListener代替。 - Ivan
.setTypeFace(null, .. ) 将移除已初始化的字体。如果您想使用特定的字体,请使用 Typeface typeface = ResourcesCompat.getFont(this, R.font.your_font); - Sven van Zoelen

28

如果您使用默认的TabLayout(非自定义视图),则可以使用getChildAt()方法获取选项卡的TextView。

.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) { }
    });

3
这将字体设置为粗体,但在取消选择后不会将其返回到正常字体? - filthy_wizard
4
仅当你在将文本设置为“NORMAL”时,用null替换“tabTextView.getTypeface()”才能使该解决方案起作用。 - Zoran P
1
@Zoran,你的评论起作用了。如何确保ViewPager创建时第一个/默认选择的选项卡是加粗的? - saintjab
1
mMainTabs 是从哪里来的? - Mehdi Karamosly
2
@mehdikaramosly 的 mMainTabs 是 TabLayout。 - hoi
显示剩余2条评论

7
我知道这是一个老问题,但我想到了一个更好的解决方案: 我创建了这个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)
            }
        }
    }
}

3

可以通过使用Tab CustomView在程序中添加加粗文字,将TextView加载到该CustomView中并在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) {
    }

这里是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>

这里是布局的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" />

2
在我的情况下,setTypeface 在标签初始化之后无法正常工作,因此我需要使用 post 方法等待 TextView 布局完成然后再使用 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)
            }
        }
    }
})

2
这是一个用Kotlin编写的解决方案代码。
 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?) {

        }

    })

1
我应用了hoi的答案,该答案适用于没有自定义视图的默认TabLayout,对我来说效果最好。但我实际上需要的是在选中一个标签时将TabItem内的文本更改为更粗的字体。所以在遵循hoi的解决方案后,我稍微修改了代码以适应我的需求。我留下这个答案,以防有人试图实现类似的功能:
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
}

这对我有效。 - mikail yusuf

1
对我来说,上述解决方案的问题在于使用 Typeface.NORMAL 重置。
SetTypeface(null, Typeface.NORMAL);

我的选项卡默认字体无法重置为我的字体。因此,我必须在更改之前保存默认字体,以便在取消选择选项卡时将字体重置为默认字体。

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);
}

1
你可以在你的TabLayout上使用这个。
app:tabSelectedTextAppearance="@style/TabSelected"

风格可以是这样的:

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

无法找到 com.google.android.material.tabs.TabLayout 的属性,我不知道你从哪里得到的这个! - Kishan Solanki
1
tabSelectedTextAppearance在Material 1.8.0-alpha02中被添加。 - Edward Moya
请提供参考文献。 - Kishan Solanki

0

这在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) { }
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接