Android - How to change bottom navigation bar text's font family
Asked Answered
K

12

56

I have created a bottom bar navigation in my android page. But now I want to apply the custom font-family in bottom navigation texts.

This is the bottom navigation code in .xml file:

<android.support.design.widget.BottomNavigationView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/bottomNavView_Bar"
            android:background="@drawable/white_grey_border_top"
            app:menu="@menu/bottom_navigation_menu">
</android.support.design.widget.BottomNavigationView>

Also, code in bottom_navigation_menu.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
      >

    <item
        android:id="@+id/ic_newsfeed"
        android:icon="@drawable/ic_menu_camera"
        android:title="NEWSFEED"
        />

        <item
            android:id="@+id/ic_explorer"
            android:icon="@drawable/ic_home_black_24dp"
            android:title="EXPLORER"
            />
        <item
            android:id="@+id/ic_notify"
            android:icon="@drawable/ic_notifications_black_24dp"
            android:title="NOTIFY"
            />
        <item
            android:id="@+id/ic_more"
            android:icon="@drawable/ic_dashboard_black_24dp"
            android:title="MORE"
            />

</menu>

Help would be appreciated.

Thanks in advance!

Keelboat answered 10/8, 2017 at 5:11 Comment(4)
this links may help you link1, link 2, link 3Conceptacle
try this #34612119Arbuthnot
Have you checked above links @Neha Beniwal ??Ploughboy
all the links above are for drawers or menu item and really relevant to the question. Don't even bother check them.Dudek
R
141

add the font file in the res/font/ folder to bundle fonts as resources

then

You can change it using style resources. In your styles.xml:

<style name="Widget.BottomNavigationView" 
    parent="Widget.Design.BottomNavigationView">
    <item name="fontFamily">@font/your_font</item>
</style>

Then apply it as a theme in your view:

<android.support.design.widget.BottomNavigationView
    ...
    android:theme="@style/Widget.BottomNavigationView"
/>

Just checked on my app, it works fine.

reference: https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html#fonts-in-code

Raeannraeburn answered 14/12, 2017 at 8:55 Comment(4)
Thanks. This answer should be marked as accepted. In my case, I am using Calligraphy library so my style xml was like <item name="fontPath">fonts/lato_medium.ttf</item>Ibarra
Be aware that if you want to change your text's font you have to specify : name="fontFamily" and NOT name="android:fontFamily"Shrader
This answer works but it also overrides the default animationLeery
For me, this answer moves the label above the icon and removes the spacingUlcerate
O
56

In your layout:

<com.google.android.material.bottomnavigation.BottomNavigationView
    ...
    app:itemTextAppearanceActive="@style/BottomNavigationViewTextStyle"
    app:itemTextAppearanceInactive="@style/BottomNavigationViewTextStyle"
    ... />

In your styles.xml:

<style name="BottomNavigationViewTextStyle">
    ...
    <item name="android:fontFamily">@font/whatever_font</item>
    ...
</style>
Opponent answered 19/11, 2018 at 16:50 Comment(4)
this is better than A. Kazarovets's answer because it doesn't override and screw with animationHalbeib
FYI: This didn't work for me with android:fontFamily, only with just fontFamily (the equivalent of app:fontFamily)Quickstep
Good Answer it is working with Theme.MaterialComponents styleDarcie
This worked for me, without breaking animation or the text label placementUlcerate
G
12

If you have a CustomFont in "Asset Folder" and you want to set in your "Bottom Navigation" use this code

        public static void persian_iran_font(final Context context, final View v) {
            try {
                if (v instanceof ViewGroup) {
                    ViewGroup vg = (ViewGroup) v;
                    for (int i = 0; i < vg.getChildCount(); i++) {
                        View child = vg.getChildAt(i);
                        persian_iran_font(context, child);
                    }
                } else if (v instanceof TextView) {
                    ((TextView) v).setTypeface(Typeface.createFromAsset(context.getAssets(), "teshrinarmedium.otf"));
                }
            } catch (Exception e) {
            }
        }
    

And then use methode in your MainActivity Like This

  BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
  persian_iran_font(getApplicationContext(), navigation);

kotlin Version

fun persian_iran_font(context: Context, v: View) {
    try {
        if (v is ViewGroup) {
            val vg = v as ViewGroup
            for (i in 0 until vg.childCount) {
                val child: View = vg.getChildAt(i)
                persian_iran_font(context, child)
            }
        } else if (v is TextView) {
            (v as TextView).setTypeface(
                Typeface.createFromAsset(
                    context.getAssets(),
                    "teshrinarmedium.otf"
                )
            )
        }
    } catch (e: Exception) {
    }
}

Goodluck

Grayce answered 1/12, 2018 at 6:12 Comment(2)
why did you extends Font class from AppCompatActivity?Equilibrate
@hassanmoradnezhad we needed context and view so had to extends from AppCompatActivityGrayce
S
9

This can be done by overriding onLayout method of BottomNavigationView class then using the extended tag. This approach also shows all menu titles and disables shifting.

public final class ExtendedBottomNavigationView extends BottomNavigationView{
    private final Context context;
    private Typeface fontFace = null;

    public ExtendedBottomNavigationView(Context context, AttributeSet attrs){
        super(context, attrs);
        this.context = context;
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom){
        super.onLayout(changed, left, top, right, bottom);
        final ViewGroup bottomMenu = (ViewGroup)getChildAt(0);
        final int bottomMenuChildCount = bottomMenu.getChildCount();
        BottomNavigationItemView item;
        View itemTitle;
        Field shiftingMode;

        if(fontFace == null){
            fontFace = Typeface.createFromAsset(context.getAssets(), context.getString(R.string.VazirBold));
        }
        try {
            //if you want to disable shiftingMode:
            //shiftingMode is a private member variable so you have to get access to it like this:
            shiftingMode = bottomMenu.getClass().getDeclaredField("mShiftingMode");
            shiftingMode.setAccessible(true);
            shiftingMode.setBoolean(bottomMenu, false);
            shiftingMode.setAccessible(false);
        } catch (NoSuchFieldException e){
            e.printStackTrace();
        } catch (IllegalAccessException e){e.printStackTrace();}

        for(int i=0; i<bottomMenuChildCount; i++){
            item = (BottomNavigationItemView)bottomMenu.getChildAt(i);
            //this shows all titles of items
            item.setChecked(true);
            //every BottomNavigationItemView has two children, first is an itemIcon and second is an itemTitle
            itemTitle = item.getChildAt(1);
            //every itemTitle has two children, first is a smallLabel and second is a largeLabel. these two are type of AppCompatTextView
            ((TextView)((BaselineLayout) itemTitle).getChildAt(0)).setTypeface(fontFace, Typeface.BOLD);
            ((TextView)((BaselineLayout) itemTitle).getChildAt(1)).setTypeface(fontFace, Typeface.BOLD);
        }
    }
}

Then use it like this:

<your.package.name.ExtendedBottomNavigationView android:id="@id/bottomMenu" style="@style/bottomMenu"/>
Symbolism answered 2/10, 2017 at 11:0 Comment(0)
N
7

For Kotlin Lover

Create an extension class for custom asset font

    /**
      * Method for Bottom Navigation Font Family
      *@param view
      *
      * */
private fun navigationTextFont(view: View) {
    if (view is ViewGroup) {
        for (i in 0 until view.childCount) {
            val child = view.getChildAt(i)
            navigationTextFont(child)
        }
    } else if (view is TextView) {
        // font from asset
        view.typeface = Typeface.createFromAsset(this.assets, "fonts/roboto_bold.ttf")
        
        // Or Font From resource
        view.typeface = ResourcesCompat.getFont(this,R.font.roboto_bold)
    }
}

Now call this extension

   navigationTextFont(yourNavigationViewId)

Good Luck

Notify answered 5/8, 2020 at 12:3 Comment(0)
J
6

Per https://material.io/develop/android/components/bottom-navigation-view/, just set a fontFamily item for the TextAppearance.MaterialComponents.Caption style and it’ll Just Work. com.google.android.material.bottomnavigation.BottomNavigationView will use this by default.

Just know other components that rely on TextAppearance.MaterialComponents.Caption will get changed as well, but this might be desirable.

<style name="TextAppearance.MaterialComponents.Caption" parent="AppMaterialComponentsTheme">
        <item name="fontFamily">@font/example</item>
</style>
Jus answered 8/12, 2018 at 18:52 Comment(0)
M
6

Kotlin language:

1: Create a file with a custom name, ex: BottomNavigationViewExtension.kt

2: Put the code below:

import android.graphics.Typeface
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import com.google.android.material.bottomnavigation.BottomNavigationView

fun BottomNavigationView.changeNavTypeface(typeface: Typeface) {
    val view: View = this
    checker(view, typeface)

}
private fun checker(view: View, typeface: Typeface) {
    if (view is ViewGroup) {
        for (i in 0 until view.childCount) {
            val child = view.getChildAt(i)
            checker(child, typeface)
        }
    } else if (view is TextView) {
        view.typeface = typeface
    }
}

3: Usage:

navView.changeNavTypeface(
    Typeface.createFromAsset(
        assets,
        "fonts/IRANSansMobile.ttf"
    )
)
Muddle answered 10/9, 2020 at 13:42 Comment(0)
O
4
public void setNavigationTypeface() {
        final Typeface avenirHeavy = Typeface.createFromAsset(this.getAssets(), "font2/Avenir-Heavy.ttf"); //replace it with your own font
        ViewGroup navigationGroup = (ViewGroup) bottomNavView.getChildAt(0);
        for (int i = 0; i < navigationGroup.getChildCount(); i++) {
            ViewGroup navUnit = (ViewGroup) navigationGroup.getChildAt(i);
            for (int j = 0; j < navUnit.getChildCount(); j++) {
                View navUnitChild = navUnit.getChildAt(j);
                if (navUnitChild instanceof BaselineLayout) {
                    BaselineLayout baselineLayout = (BaselineLayout) navUnitChild;
                    for (int k = 0; k < baselineLayout.getChildCount(); k++) {
                        View baselineChild = baselineLayout.getChildAt(k);
                        if (baselineChild instanceof TextView) {
                            TextView textView = (TextView) baselineChild;
                            textView.setTypeface(avenirHeavy);
                        }
                    }
                }
            }
        }
    }
Othilia answered 2/8, 2018 at 13:10 Comment(0)
L
3

style.xml

<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>

</style>
<style name="Widget.BottomNavigationView"
    parent="Widget.Design.BottomNavigationView">
    <item name="fontFamily">@font/segoe_ui_semibold</item>
</style>
</resources>

activity_main.xml

 <com.google.android.material.bottomnavigation.BottomNavigationView
    android:id="@+id/bottom_navigation_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:background="#FFF"
    app:itemIconTint="@color/navigation_bottom"
    app:itemTextColor="@color/navigation_bottom"
    app:labelVisibilityMode="labeled"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    android:theme="@style/Widget.BottomNavigationView" (this line)
    app:menu="@menu/nav_items" />
Lou answered 26/10, 2020 at 10:21 Comment(0)
K
3

I am able to change the Font family & Text size without creating any classes/functions.

Add these lines to Themes.xml

<style name="BottomNavigationView">
    <item name="fontFamily">@font/my_bold_font</item>
    <item name="android:textSize">10sp</item>
</style>

Add android:theme to your BottomNavigationView.

<com.google.android.material.bottomnavigation.BottomNavigationView
    ...
    ... Add the line below.
    ...
    android:theme="@style/BottomNavigationView" />
Kenlay answered 23/8, 2022 at 11:47 Comment(1)
material is causing problems in versions 1.8.0+Ramentum
T
2

Kotlin Code of custom BottomNavigationView to set custom font:

1.Keep a font to assets directory of your android studio project. Here I used my font "SolaimanLipi_20-04-07.ttf"

2.Copy below kotlin code and paste to your android studio project.

class FontBottomNavigationView : BottomNavigationView {


constructor(context: Context) : super(context) {

}

constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {

}

constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {

}

private var fontFace: Typeface? = null

override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
    super.onLayout(changed, left, top, right, bottom)

    val bottomMenu = getChildAt(0) as ViewGroup
    val bottomMenuChildCount: Int = bottomMenu.childCount
    var item: BottomNavigationItemView? = null
    var itemTitle: View? = null
    var shiftingMode: Field? = null

    if (fontFace == null){
        fontFace = Typeface.createFromAsset(context.assets, "SolaimanLipi_20-04-07.ttf") // font from assets directory
    }

    try {
        shiftingMode = bottomMenu.javaClass.getDeclaredField("mShiftingMode")
        shiftingMode.isAccessible = true
        shiftingMode.setBoolean(bottomMenu, false)
        shiftingMode.isAccessible = false
    } catch (e: Exception){
        e.printStackTrace()
    }

    for (i in 0..bottomMenuChildCount){
        try {
            item = bottomMenu.getChildAt(i) as BottomNavigationItemView
            itemTitle = item.getChildAt(1)
            ((itemTitle as BaselineLayout).getChildAt(0) as AppCompatTextView).typeface = fontFace
            ((itemTitle as BaselineLayout).getChildAt(1) as AppCompatTextView).typeface = fontFace
        } catch (e: Exception){
            e.printStackTrace()
        }

    }

}}

3.Use on xml file as like below:

<com.example.projectname.FontBottomNavigationView
        android:id="@+id/nav_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="0dp"
        android:layout_marginEnd="0dp"
        android:background="?android:attr/windowBackground"
        app:menu="@menu/bottom_nav_menu" />

@Arash answer helped:

Trunk answered 5/9, 2019 at 12:50 Comment(0)
N
2

Long story short :

/**
 * @param view The bottom navigation view to update
 * @param tf The typeface which the text should be displayed
 */
public static void setAllTypefaces(View view, Typeface tf) {
    if (view instanceof ViewGroup) {
        for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++)
            setAllTypefaces(((ViewGroup) view).getChildAt(i),tf);
    } else if (view instanceof TextView) ((TextView) view).setTypeface(tf);
}

enter image description here

Newsome answered 3/8, 2021 at 16:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.