You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TabLayout+ViewPager组合下TTF格式标签标题字体不生效求助

我之前也遇到过这个问题!TabLayout默认确实不会直接识别Style里的自定义TTF字体,因为它内部的标签文本View是动态生成的,Style的字体设置没法直接覆盖进去。给你几个靠谱的解决方法:

方案一:自定义Tab布局(最稳定推荐)

这种方法完全由你控制Tab的样式,兼容性最好,步骤也清晰:

  1. 先创建一个自定义的Tab布局文件(比如res/layout/tab_custom_item.xml):
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/tab_title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:textSize="14sp"
    android:textColor="@color/tab_text_color_selector" <!-- 可添加选中/未选中的颜色状态 -->
    android:fontFamily="@font/your_custom_font" /> <!-- Android 8.0+ 用font目录存放字体文件 -->

如果项目需要兼容Android 8.0以下版本,不要用android:fontFamily,后续通过代码加载assets里的字体即可。

  1. 在代码中给TabLayout绑定自定义布局:
// 先完成ViewPager和TabLayout的绑定
ViewPager viewPager = findViewById(R.id.viewPager);
TabLayout tabLayout = findViewById(R.id.tabs);
viewPager.setAdapter(yourPagerAdapter);
tabLayout.setupWithViewPager(viewPager);

// 遍历每个Tab,设置自定义布局
Typeface customTypeface = Typeface.createFromAsset(getAssets(), "fonts/your_custom_font.ttf"); // 低版本兼容用这个
for (int i = 0; i < tabLayout.getTabCount(); i++) {
    TabLayout.Tab tab = tabLayout.getTabAt(i);
    if (tab != null) {
        tab.setCustomView(R.layout.tab_custom_item);
        TextView tabTitle = tab.getCustomView().findViewById(R.id.tab_title);
        tabTitle.setText(yourPagerAdapter.getPageTitle(i));
        // 低版本需要手动设置字体
        // tabTitle.setTypeface(customTypeface);
    }
}

方案二:通过反射修改内部TextView字体(适合快速调试)

如果不想自定义布局,可以用反射直接修改TabLayout内部的TextView字体,但要注意反射可能会因为库版本更新而失效:

private void applyCustomFontToTabLayout(TabLayout tabLayout) {
    try {
        // 加载自定义字体
        Typeface customFont = Typeface.createFromAsset(getAssets(), "fonts/your_custom_font.ttf");
        
        // 反射获取TabLayout的文本样式属性
        Field textAppearanceField = TabLayout.class.getDeclaredField("mTabTextAppearance");
        textAppearanceField.setAccessible(true);
        int textAppearanceResId = textAppearanceField.getInt(tabLayout);
        TextAppearanceSpan appearanceSpan = new TextAppearanceSpan(this, textAppearanceResId);
        
        // 获取默认的文本颜色状态列表
        Field textColorField = TextAppearanceSpan.class.getDeclaredField("mTextColor");
        textColorField.setAccessible(true);
        ColorStateList textColor = (ColorStateList) textColorField.get(appearanceSpan);
        
        // 遍历每个Tab,用SpannableString设置字体
        for (int i = 0; i < tabLayout.getTabCount(); i++) {
            TabLayout.Tab tab = tabLayout.getTabAt(i);
            if (tab != null && tab.getText() != null) {
                SpannableString spannableTitle = new SpannableString(tab.getText());
                // 自定义TypefaceSpan来兼容不同API版本
                spannableTitle.setSpan(new CustomTypefaceSpan("", customFont), 0, spannableTitle.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
                // 保留原来的文本颜色状态
                spannableTitle.setSpan(new ForegroundColorSpan(textColor.getColorForState(tab.getView().getDrawableState(), textColor.getDefaultColor())), 0, spannableTitle.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
                tab.setText(spannableTitle);
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

// 自定义TypefaceSpan,解决默认类的兼容性问题
public static class CustomTypefaceSpan extends TypefaceSpan {
    private final Typeface customTypeface;

    public CustomTypefaceSpan(String family, Typeface typeface) {
        super(family);
        this.customTypeface = typeface;
    }

    @Override
    public void updateDrawState(TextPaint ds) {
        applyTypeface(ds, customTypeface);
    }

    @Override
    public void updateMeasureState(TextPaint paint) {
        applyTypeface(paint, customTypeface);
    }

    private void applyTypeface(Paint paint, Typeface typeface) {
        int oldStyle = paint.getTypeface() != null ? paint.getTypeface().getStyle() : 0;
        int fakeStyle = oldStyle & ~typeface.getStyle();

        if ((fakeStyle & Typeface.BOLD) != 0) {
            paint.setFakeBoldText(true);
        }
        if ((fakeStyle & Typeface.ITALIC) != 0) {
            paint.setTextSkewX(-0.25f);
        }

        paint.setTypeface(typeface);
    }
}

调用方法:在tabLayout.setupWithViewPager(viewPager)之后执行applyCustomFontToTabLayout(tabLayout)即可。

方案三:AndroidX下的Style配置(需注意版本兼容性)

如果你已经迁移到AndroidX的Material Components库,可以尝试通过Style直接配置,但这个方法在部分库版本中可能不生效:

<!-- 你的CustomTabLayout Style -->
<style name="CustomTabLayout" parent="Widget.MaterialComponents.TabLayout">
    <item name="tabTextAppearance">@style/CustomTabTextAppearance</item>
    <item name="android:background">#eceff1</item>
    <item name="tabMode">fixed</item>
    <item name="tabGravity">fill</item>
</style>

<!-- 自定义文本样式,指定字体 -->
<style name="CustomTabTextAppearance" parent="TextAppearance.MaterialComponents.Tab">
    <item name="android:fontFamily">@font/your_custom_font</item> <!-- Android 8.0+ -->
    <!-- 低版本可以尝试用:<item name="fontFamily">@font/your_custom_font</item> -->
</style>

个人最推荐方案一,不仅字体问题能解决,后续要修改Tab的样式(比如加图标、调整间距)也更方便。

内容的提问来源于stack exchange,提问作者Seema

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:19:04