web-dev-qa-db-fra.com

Changer la police du texte de l'onglet dans le support de conception Android TabLayout

J'essaie de travailler sur la nouvelle TabLayout de la bibliothèque de conception Android.

Je souhaite modifier le texte de l'onglet en police personnalisée. Et, j'ai essayé de chercher un style lié à TabLayout, mais j'ai fini par this

S'il vous plaît guider comment puis-je changer les polices de texte de tabulation.

81
Dory

Créez un TextView à partir de Java Code ou XML comme ceci

<?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"
/>

Assurez-vous de conserver l'ID tel qu'il est ici car le TabLayout vérifie cet ID si vous utilisez l'affichage de texte personnalisé.

Ensuite, à partir du code, gonflez cette disposition, définissez la variable Typeface sur cette vue textuelle et ajoutez cette vue personnalisée à l'onglet.

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);
}
28
Farmaan Elahi

Si vous utilisez TabLayout et que vous souhaitez modifier la police, vous devez ajouter une nouvelle boucle for à la solution précédente, comme ceci:

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

Veuillez vous référer à changer le style de police dans les onglets de la barre d’action en utilisant sherlock

145
praveen Sharma

Créez votre propre style personnalisé et utilisez le style parent comme parent="@Android:style/TextAppearance.Widget.TabWidget"

Et dans votre disposition d'onglet utilisez ce style comme app:tabTextAppearance="@style/tab_text"

Exemple: Style:

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

Exemple: Composant de présentation d'onglets:

<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" />
51
Milind Mevada

Grande réponse de Praveen Sharma. Juste un petit ajout: Au lieu d'utiliser changeTabsFont() partout où vous avez besoin de TabLayout, vous pouvez simplement utiliser votre propre 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);
            }
        }
    }

}

Et encore une chose .TabView est une LinearLayout avec TextView à l'intérieur (elle peut aussi éventuellement contenir ImageView). Vous pouvez donc rendre le code encore plus simple:

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

Mais je ne recommanderais pas de cette façon. Si la mise en œuvre de TabLayout change, ce code peut ne pas fonctionner correctement ou même se bloquer.

Une autre façon de personnaliser TabLayout consiste à y ajouter une vue personnalisée. Voici le grand exemple .

47
Andrei Aulaska

La méthode suivante changera la police dans ViewGroup entière de manière récursive. J'ai choisi cette méthode parce que vous n'avez pas à vous soucier de la structure interne de TabLayout. J'utilise Calligraphy library pour définir une police.

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

Pour le support de conception 23.2.0, en utilisant setupWithViewPager, vous devrez déplacer le code de addTab (onglet) à addTab (onglet, boolean setSelected).

11
ejw

Eh bien, je l’ai trouvé simple en 23.4.0 sans utiliser de boucle. Remplacez simplement addTab (onglet @NonNull, boolean setSelected) comme suggéré par @ejw.

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

Et voici le 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" />

J'espère que ça pourrait aider :)

8
elsennov

Vous pouvez l'utiliser, cela fonctionne pour moi.

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

En tant que Andrei répondu, vous pouvez modifier la fontface en développant TabLayout class. Et comme Penzzz a dit, vous ne pouvez pas le faire avec addTab . Remplacer onLayout méthode comme suit:

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

La méthode onLayout doit être écrasée, car lorsque vous utilisez setupWithViewPager pour lier TabLayout avec ViewPager, vous devez définir le texte des onglets soit avec la méthode setText, soit dans PagerAdapter, puis, le cas échéant, avec la méthode onLayout. le ViewGroup parent (TabLayout) et c'est l'endroit idéal pour définir une fontface. (Changer un texte TextView provoque l'appel de la méthode onLayout de son parent - Un tabView a deux enfants, l'un est ImageView l'autre est TextView)

Une autre solution:

Premièrement, ces lignes de code:

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

Dans la solution ci-dessus, doit être écrit en dehors de deux boucles.

Mais meilleure solution pour API> = 16 utilise Android: fontFamily :

Créez un répertoire de ressources Android named et copiez la police souhaitée dans le répertoire.

Ensuite, utilisez ces styles:

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

Pour utiliser la prise en charge des polices dans la fonction XML sur les appareils exécutant Android 4.1 (niveau d'API 16) et supérieur, utilisez la bibliothèque de support technique 26+.

  1. Clic droit res dossier
  2. Nouveau -> Répertoire des ressources Android-> Sélectionner la police -> Ok
  3. Placez votre fichier myfont.ttf dans le dossier de polices nouvellement créé.

Sur res/values/styles.xml ajouter:

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

Dans le fichier de mise en page, ajoutez app: tabTextAppearance = "@ 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" />

Veuillez vous reporter à [polices en xml]. ( https://developer.Android.com/guide/topics/ui/look-and-feel/fonts-in-xml )

5
Thomas V J

Ma méthode Resolve juste comme ça, change le texte de l'onglet spécifié, 

 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);
 }
3
Smish jack

L'extension Kotlin qui a fonctionné pour moi:

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

Mon 2p, Kotlin avec vérification des références, applicable partout car il va s'arrêter si quelque chose ne va pas.

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) }
            }
}
1
Rafael Ruiz Muñoz
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>
0
sudhakara

Et voici mon implémentation dans Kotlin qui autorise également le changement de police pour les onglets sélectionnés et non sélectionnés.

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 = [email protected]
            text = position.toString()
        }
    }
}

dans 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>
0
Yvgen

Avec les fonctions d'extension kotlin, utilisez ceci:

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

}

0