在 Android 设计支持库 TabLayout 中更改选项卡文本字体

139

我正在尝试使用Android设计库中的新TabLayout

我想要将选项卡文本更改为自定义字体。我尝试搜索与TabLayout相关的样式,但最终找到了这里的内容。

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


3
使用 Spannable String。 - NullByte
21个回答

7

23.4.0版本中,我发现不需要使用循环就可以轻松实现。只需按照@ejw的建议重写addTab(@NonNull Tab 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" />

希望这能有所帮助 :)

1
但是如何设置tabSelectedTextColor和tabTextColor? - Mostafa Imran
@MostafaImran,你的版本应该使用状态列表选择器来指定android:textColor="@color/graylove"的选中状态颜色。 - AA_PV

4

我用过的 Kotlin 扩展:

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

3
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>

3
我的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);
 }

2
您可以通过在style.xml文件中使用以下样式来更改选项卡图标的文本外观。这是样式:

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

2

以下是我在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()
        }
    }
}

in 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>

tabs.getTabAt(1)?.text在设置后无法动态更改文本。 - shanraisshan

1
我的看法是,Kotlin具有引用检查功能,在任何地方都适用,如果出现问题,它会停止运行。
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) }
            }
}

0
            tabLayout = findViewById(R.id.tabLayout);
    //Update Tab layout indicator and text color
            tabLayout.setSelectedTabIndicatorColor(Color.GREY);
            tabLayout.setTabTextColors(Color.RED,Color.GREEN);
    
    //setup tablayout with view pager
            tabLayout.setupWithViewPager(viewPager);
    //after set up with view pager call update font of tablayout text
            for (int a = 0; a < tabLayout.getTabCount(); a++){
                 TabLayout.Tab selectedTab = tabLayout.getTabAt(a);
                 setTabTypeface(selectedTab, ResourcesCompat.getFont(this,R.font.dancingscript_bold));
                }

    //add this function to your class 
     private void setTabTypeface(TabLayout.Tab tab, Typeface typeface){
            for(int i=0; i<tab.view.getChildCount(); i++) {
                View tabViewChild = tab.view.getChildAt(i);
                if (tabViewChild instanceof TextView)
                    ((TextView) tabViewChild).setTypeface(typeface);
            }
        }

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

0
使用 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))
        }
    }
}

}


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