在安卓设计支持 TabLayout 中更改选项卡文本的字体

我正在尝试从机器人设计库中开发新的 TabLayout

我想改变选项卡文本为 自定义字体。而且,我试图搜索一些造型相关的 TabLayout,但结束了 这个

请指导我如何更改选项卡文本字体。

105843 次浏览

如果你正在使用 TabLayout并且你想要改变字体,你必须像下面这样在以前的解决方案中添加一个新的 for 循环:

private void changeTabsFont() {
ViewGroup vg = (ViewGroup) tabLayout.getChildAt(0);
int tabsCount = vg.getChildCount();
for (int j = 0; j < tabsCount; j++) {
ViewGroup vgTab = (ViewGroup) vg.getChildAt(j);
int tabChildsCount = vgTab.getChildCount();
for (int i = 0; i < tabChildsCount; i++) {
View tabViewChild = vgTab.getChildAt(i);
if (tabViewChild instanceof TextView) {
((TextView) tabViewChild).setTypeface(Font.getInstance().getTypeFace(), Typeface.NORMAL);
}
}
}
}

请参阅 使用夏洛克改变操作栏标签的字体样式

来自 Praveen Sharma 的精彩回答,只是一个小小的补充: 与在需要 TabLayout的任何地方使用 changeTabsFont()不同,您可以简单地使用自己的 CustomTabLayout

import android.content.Context;
import android.graphics.Typeface;
import android.support.design.widget.TabLayout;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;


public class CustomTabLayout extends TabLayout {
private Typeface mTypeface;


public CustomTabLayout(Context context) {
super(context);
init();
}


public CustomTabLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}


public CustomTabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}


private void init() {
mTypeface = Typeface.createFromAsset(getContext().getAssets(), "fonts/Roboto-Regular.ttf");
}


@Override
public void addTab(Tab tab) {
super.addTab(tab);


ViewGroup mainView = (ViewGroup) getChildAt(0);
ViewGroup tabView = (ViewGroup) mainView.getChildAt(tab.getPosition());


int tabChildCount = tabView.getChildCount();
for (int i = 0; i < tabChildCount; i++) {
View tabViewChild = tabView.getChildAt(i);
if (tabViewChild instanceof TextView) {
((TextView) tabViewChild).setTypeface(mTypeface, Typeface.NORMAL);
}
}
}


}

还有一件事。 TabView是一个内含 TextViewLinearLayout(它也可以选择包含 ImageView)。所以你可以让代码更简单:

@Override
public void addTab(Tab tab) {
super.addTab(tab);


ViewGroup mainView = (ViewGroup) getChildAt(0);
ViewGroup tabView = (ViewGroup) mainView.getChildAt(tab.getPosition());
View tabViewChild = tabView.getChildAt(1);
((TextView) tabViewChild).setTypeface(mTypeface, Typeface.NORMAL);
}

但是我不推荐这种方式。如果 TabLayout实现发生变化,这段代码可能会不正常工作,甚至崩溃。

另一种自定义 TabLayout的方法是添加自定义视图。

改变

if (tabViewChild instanceof TextView) {

为了

if (tabViewChild instanceof AppCompatTextView) {

使其能够与 android.support. design. widget. TabLayout 一起工作(至少来自 com.android.support: design: 23.2.0)

对于设计支持23.2.0,使用 setupWithViewPager,您必须将代码从 addTab (Tab Tab)移动到 addTab (Tab Tab,boolean setSelected)。

下面的方法将递归地更改整个 ViewGroup的字体。我选择这个方法是因为您不必关心 TabLayout的内部结构。我使用 书法库来设置字体。

void changeFontInViewGroup(ViewGroup viewGroup, String fontPath) {
for (int i = 0; i < viewGroup.getChildCount(); i++) {
View child = viewGroup.getChildAt(i);
if (TextView.class.isAssignableFrom(child.getClass())) {
CalligraphyUtils.applyFontToTextView(child.getContext(), (TextView) child, fontPath);
} else if (ViewGroup.class.isAssignableFrom(child.getClass())) {
changeFontInViewGroup((ViewGroup) viewGroup.getChildAt(i), fontPath);
}
}
}

我在23.4.0中发现它很简单,没有使用循环。按照@ejw 的建议,只需覆盖 addTab (@NonNull Tab,boolean setSelected)。

@Override
public void addTab(@NonNull Tab tab, boolean setSelected) {
CoralBoldTextView coralTabView = (CoralBoldTextView) View.inflate(getContext(), R.layout.coral_tab_layout_view, null);
coralTabView.setText(tab.getText());
tab.setCustomView(coralTabView);


super.addTab(tab, setSelected);
}

这是 XML

<?xml version="1.0" encoding="utf-8"?>
<id.co.coralshop.skyfish.ui.CoralBoldTextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/custom_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:gravity="center"
android:singleLine="true"
android:textColor="@color/graylove"
android:textSize="@dimen/tab_text_size" />

希望能有所帮助:)

我的 Resolve 方法就像这样,更改“指定”选项卡文本,

 ViewGroup vg = (ViewGroup) tabLayout.getChildAt(0);
ViewGroup vgTab = (ViewGroup) vg.getChildAt(1);
View tabViewChild = vgTab.getChildAt(1);
if (tabViewChild instanceof TextView) {
((TextView) tabViewChild).setText(str);
}

正如 安德烈所回答的,您可以通过扩展 TabLayout类来更改字体。就像 彭兹说的,你不能用 AddTab方法做。重写 在布局上方法如下:

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom){
super.onLayout(changed, left, top, right, bottom);


final ViewGroup tabStrip = (ViewGroup)getChildAt(0);
final int tabCount = tabStrip.getChildCount();
ViewGroup tabView;
int tabChildCount;
View tabViewChild;


for(int i=0; i<tabCount; i++){
tabView = (ViewGroup)tabStrip.getChildAt(i);
tabChildCount = tabView.getChildCount();
for(int j=0; j<tabChildCount; j++){
tabViewChild = tabView.getChildAt(j);
if(tabViewChild instanceof AppCompatTextView){
if(fontFace == null){
fontFace = Typeface.createFromAsset(context.getAssets(), context.getString(R.string.IranSans));
}
((TextView) tabViewChild).setTypeface(fontFace, Typeface.BOLD);
}
}
}
}

必须覆盖 onLayout 方法,因为当您使用 SetupWithViewPager方法将 TabLayout 与 ViewPager 绑定时,您必须使用 setText 方法或在 PagerAdapter 中设置选项卡文本,当这种情况发生时,在父 ViewGroup (TabLayout)上调用 onLayout 方法,这是放置设置字体的地方。(更改 TextView 文本会导致调用其父节点的 onLayout 方法—— tabView 有两个子节点,一个是 ImageView,另一个是 TextView)

另一种解决方案:

首先,这些代码行:

    if(fontFace == null){
fontFace = Typeface.createFromAsset(context.getAssets(), context.getString(R.string.IranSans));
}

在上面的解决方案中,应该写在两个循环之外。

但对于 空气污染指数 > = 16来说,更好的解决方案是使用 机器人: fontFamily:

创建一个名为 font 的 Android 资源目录并将所需的字体复制到目录中。

然后使用以下风格:

<style name="tabLayoutTitles">
<item name="android:textColor">@color/white</item>
<item name="android:textSize">@dimen/appFirstFontSize</item>
<item name="android:fontFamily">@font/vazir_bold</item>
</style>


<style name="defaultTabLayout">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">@dimen/defaultTabLayoutHeight</item>
<item name="android:gravity">right</item>
<item name="tabTextAppearance">@style/tabLayoutTitles</item>
<item name="tabSelectedTextColor">@color/white</item>
<item name="tabIndicatorColor">@color/white</item>
<item name="tabIndicatorHeight">@dimen/accomTabIndicatorHeight</item>
<item name="tabMode">fixed</item>
<item name="tabGravity">fill</item>
<item name="tabBackground">@drawable/rectangle_white_ripple</item>
<item name="android:background">@color/colorPrimary</item>
</style>

从 Java 代码或 XML 创建 TextView,如下所示

<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@android:id/text1"
android:layout_width="match_parent"
android:textSize="15sp"
android:textColor="@color/tabs_default_color"
android:gravity="center"
android:layout_height="match_parent"
/>

如果您使用自定义文本视图,那么一定要保留这里的 ID,因为 TabLayout 会检查这个 ID

然后从代码中膨胀这个布局,并在该文本视图上设置自定义 Typeface,并将这个自定义视图添加到选项卡中

for (int i = 0; i < tabLayout.getTabCount(); i++) {
//noinspection ConstantConditions
TextView tv = (TextView)LayoutInflater.from(this).inflate(R.layout.custom_tab,null)
tv.setTypeface(Typeface);
tabLayout.getTabAt(i).setCustomView(tv);
}

你可以用这个,对我有用。

 private void changeTabsFont() {
ViewGroup vg = (ViewGroup) tabLayout.getChildAt(0);
int tabsCount = vg.getChildCount();
for (int j = 0; j < tabsCount; j++) {
ViewGroup vgTab = (ViewGroup) vg.getChildAt(j);
int tabChildsCount = vgTab.getChildCount();
for (int i = 0; i < tabChildsCount; i++) {
View tabViewChild = vgTab.getChildAt(i);
if (tabViewChild instanceof TextView) {
AssetManager mgr = getActivity().getAssets();
Typeface tf = Typeface.createFromAsset(mgr, "fonts/Roboto-Regular.ttf");//Font file in /assets
((TextView) tabViewChild).setTypeface(tf);
}
}
}
}

创建自己的自定义样式并使用父样式作为 parent="@android:style/TextAppearance.Widget.TabWidget"

在选项卡布局中,使用此样式作为 app:tabTextAppearance="@style/tab_text"

例如: 风格:

<style name="tab_text" parent="@android:style/TextAppearance.Widget.TabWidget">
<item name="android:fontFamily">@font/poppins_regular</item>
</style>

示例: 选项卡布局组件:

<android.support.design.widget.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:tabTextAppearance="@style/tab_text" />

我的2便士,科特林与参考检查,适用于任何地方,因为它会停止,如果有什么是错误的。

private fun setTabLayouFont(tabLayout: TabLayout) {
val viewGroupTabLayout = tabLayout.getChildAt(0) as? ViewGroup?
(0 until (viewGroupTabLayout?.childCount ?: return))
.map { viewGroupTabLayout.getChildAt(it) as? ViewGroup? }
.forEach { viewGroupTabItem ->
(0 until (viewGroupTabItem?.childCount ?: return))
.mapNotNull { viewGroupTabItem.getChildAt(it) as? TextView }
.forEach { applyDefaultFontToTextView(it) }
}
}

要在运行 Android 4.1(API 级别16)或更高的设备上使用 XML特性中的字体支持,请使用 Support Library 26 + 。

  1. 右键单击 res 文件夹
  2. 新建-> Android 资源目录-> select font-> OK
  3. myfont.ttf文件放在新创建的字体文件夹中

res/values/styles.xml上添加:

<style name="customfontstyle" parent="@android:style/TextAppearance.Small">
<item name="android:fontFamily">@font/myfont</item>
</style>

在布局文件中添加应用程序: tabText卖相 = “@style/customfontstyle”,

<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabGravity="fill"
app:tabTextAppearance="@style/customfontstyle"
app:tabMode="fixed" />

请参阅[ xml 中的字体](https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml)

I think this is easier way.


<android.support.design.widget.TabLayout
android:id="@+id/tabs"
app:tabTextColor="@color/lightPrimary"
app:tabSelectedTextColor="@color/white"
style="@style/CustomTabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<style name="CustomTabLayout" parent="Widget.Design.TabLayout">
<item name="tabMaxWidth">20dp</item>
<item name="tabMode">scrollable</item>
<item name="tabIndicatorColor">?attr/colorAccent</item>
<item name="tabIndicatorHeight">2dp</item>
<item name="tabPaddingStart">12dp</item>
<item name="tabPaddingEnd">12dp</item>
<item name="tabBackground">?attr/selectableItemBackground</item>
<item name="tabTextAppearance">@style/CustomTabTextAppearance</item>
<item name="tabSelectedTextColor">?android:textColorPrimary</item>
</style>
<style name="CustomTabTextAppearance" parent="TextAppearance.Design.Tab">
<item name="android:textSize">16sp</item>
<item name="android:textStyle">bold</item>
<item name="android:textColor">?android:textColorSecondary</item>
<item name="textAllCaps">false</item>
</style>

科特林分机,对我有用:

fun TabLayout.setFont(font: FontUtils.Fonts) {
val vg = this.getChildAt(0) as ViewGroup
for (i: Int in 0..vg.childCount) {
val vgTab = vg.getChildAt(i) as ViewGroup?
vgTab?.let {
for (j: Int in 0..vgTab.childCount) {
val tab = vgTab.getChildAt(j)
if (tab is TextView) {
tab.typeface = FontUtils.getTypeFaceByFont(FontUtils.Fonts.BOLD, context)
}
}
}
}
}

对于 kotlin 扩展函数,使用以下方法:

 fun TabLayout.setFontSizeAndColor(typeface: Typeface, @DimenRes textSize: Int, @ColorRes textColor: Int) {
val viewGroup: ViewGroup = this.getChildAt(0) as ViewGroup
val tabsCount: Int = viewGroup.childCount
for (j in 0 until tabsCount) {
val viewGroupTab: ViewGroup = viewGroup.getChildAt(j) as ViewGroup
val tabChildCount: Int = viewGroupTab.childCount
for (i in 0 until tabChildCount) {
val tabViewChild: View = viewGroupTab.getChildAt(i) as View
if ( tabViewChild is TextView) {
tabViewChild.typeface = typeface
tabViewChild.gravity = Gravity.FILL
tabViewChild.maxLines = 1
tabViewChild.setTextSize(TypedValue.COMPLEX_UNIT_PX, this.resources.getDimension(textSize))
tabViewChild.setTextColor(ContextCompat.getColor(this.context, textColor))
}
}
}

}

下面是我在 Kotlin 的实现,它也允许为选中和未选中的标签更改字体。

class FontTabLayout @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
@AttrRes defStyleAttr: Int = 0
) : TabLayout(context, attrs, defStyleAttr) {


private var textSize = 14f


private var defaultSelectedPosition = 0


private var selectedTypeFace: Typeface? = ResourcesCompat.getFont(context, R.font.muli_bold)
private var normalTypeFace: Typeface? = ResourcesCompat.getFont(context, R.font.muli_regular)


@ColorInt private var selectedColor = 0
@ColorInt private var normalTextColor = 0


init {
attrs?.let { initAttrs(it) }
addOnTabSelectedListener()
}


private fun initAttrs(attrs: AttributeSet) {
val a = context.obtainStyledAttributes(attrs, R.styleable.FontTabLayout)


textSize = a.getDimensionPixelSize(R.styleable.FontTabLayout_textSize, 14).toFloat()


defaultSelectedPosition = a.getInteger(R.styleable.FontTabLayout_defaultSelectedPosition, 0)
val selectedResourceId = a.getResourceId(R.styleable.FontTabLayout_selectedTypeFace, R.font.muli_bold)
val normalResourceId = a.getResourceId(R.styleable.FontTabLayout_normalTypeFace, R.font.muli_regular)


selectedColor = a.getColor(com.google.android.material.R.styleable.TabLayout_tabSelectedTextColor, 0)
normalTextColor = a.getColor(R.styleable.FontTabLayout_normalTextColor, 0)


selectedTypeFace = ResourcesCompat.getFont(context, selectedResourceId)
normalTypeFace = ResourcesCompat.getFont(context, normalResourceId)


a.recycle()
}


private fun addOnTabSelectedListener() {
addOnTabSelectedListener(object : OnTabSelectedListenerAdapter() {


override fun onTabUnselected(tab: Tab?) {
getCustomViewFromTab(tab)?.apply {
setTextColor(normalTextColor)
typeface = normalTypeFace
}
}


override fun onTabSelected(tab: Tab?) {


getCustomViewFromTab(tab)?.apply {
setTextColor(selectedColor)
typeface = selectedTypeFace
}
}


private fun getCustomViewFromTab(tab: Tab?) = tab?.customView as? AppCompatTextView


})
}


override fun setupWithViewPager(viewPager: ViewPager?, autoRefresh: Boolean) {
super.setupWithViewPager(viewPager, autoRefresh)
addViews(viewPager)
}


private fun addViews(viewPager: ViewPager?) {
for (i in 0 until tabCount) {
val customTabView = getCustomTabView(i).apply {
typeface = if (i == defaultSelectedPosition) selectedTypeFace else normalTypeFace
val color = if (i == defaultSelectedPosition) selectedColor else normalTextColor
setTextColor(color)
text = viewPager?.adapter?.getPageTitle(i)
}


getTabAt(i)?.customView = customTabView
}
}


private fun getCustomTabView(position: Int): AppCompatTextView {
return AppCompatTextView(context).apply {
gravity = Gravity.CENTER
textSize = this@FontTabLayout.textSize
text = position.toString()
}
}
}

在 attrs.xml 中:

<declare-styleable name="FontTabLayout">
<attr name="normalTextColor" format="reference|color" />
<attr name="textSize" format="dimension" />
<attr name="defaultSelectedPosition" format="integer" />
<attr name="selectedTypeFace" format="reference" />
<attr name="normalTypeFace" format="reference" />
</declare-styleable>

如果你正在使用

资料: 1.2.0(最新版本)

<style name="MyCustomTabTextAppearance" parent="TextAppearance.Design.Tab">
<item name="fontFamily">Your Font</item>
<item name="android:fontFamily">Your Font</item>
<item name="textAllCaps">false</item>
</style>


<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabBackground="@color/colorPrimary"
app:tabGravity="fill"
app:tabIndicatorColor="@color/white"
app:tabMode="fixed"
app:tabTextAppearance="@style/MyCustomTabTextAppearance"
app:tabTextColor="@android:color/white" />

您可以通过使用 style.xml 文件中编写的样式来更改 Tab 图标的文本外观

<style name="TabItemTextAppearance" parent="TextAppearance.Design.Tab">
<item name="android:textSize">13sp</item>
<item name="fontWeight">800</item>
<item name="fontFamily">@font/balooda2_medium</item>
</style>

并在 TabLayout 中使用此样式

<com.google.android.material.tabs.TabLayout
android:id="@+id/live_tab_bar"
android:layout_width="match_parent"
android:layout_height="@dimen/_40sdp"
app:tabGravity="fill"
app:tabIndicatorGravity="stretch"
app:tabMaxWidth="0dp"
app:tabMode="fixed"
app:tabSelectedTextColor="@color/white"
app:tabTextAppearance="@style/TabItemTextAppearance"
app:tabTextColor="#354895">


<com.google.android.material.tabs.TabItem
android:id="@+id/live_tab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="লাইভ ক্লাস" />


<com.google.android.material.tabs.TabItem
android:id="@+id/recorded_tab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="রেকর্ডেড ভিডিও" />


</com.google.android.material.tabs.TabLayout>
fun TabLayout.customizeTabText() {
val viewGroup = this.getChildAt(0) as ViewGroup
for (i: Int in 0..viewGroup.childCount) {
val tabViewGroup = viewGroup.getChildAt(i) as ViewGroup?
tabViewGroup?.let {
for (j: Int in 0..tabViewGroup.childCount) {
val tab = tabViewGroup.getChildAt(j)
if (tab is TextView) {
tab.typeface = Typeface.createFromAsset(context.assets, "font.ttf")
tab.setTextSize(TypedValue.COMPLEX_UNIT_SP, 21f)
}
}
}
}
}