TabLayout+ViewPager组合下TTF格式标签标题字体不生效求助
我之前也遇到过这个问题!TabLayout默认确实不会直接识别Style里的自定义TTF字体,因为它内部的标签文本View是动态生成的,Style的字体设置没法直接覆盖进去。给你几个靠谱的解决方法:
方案一:自定义Tab布局(最稳定推荐)
这种方法完全由你控制Tab的样式,兼容性最好,步骤也清晰:
- 先创建一个自定义的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里的字体即可。
- 在代码中给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
相关产品推荐
相关产品推荐

