【问题标题】:Android - How to change bottom navigation bar text's font familyAndroid - 如何更改底部导航栏文本的字体系列
【发布时间】:2018-01-18 04:27:02
【问题描述】:

我在我的 android 页面中创建了一个底部栏导航。但现在我想在底部导航文本中应用自定义字体系列。

这是.xml文件中的底部导航代码:

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

另外,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>

我们将不胜感激。

提前致谢!

【问题讨论】:

标签: android android-layout fonts typeface


【解决方案1】:

这可以通过覆盖 BottomNavigationView 类的 onLayout 方法然后使用扩展标记来完成。此方法还显示所有菜单标题并禁用移位。

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

然后像这样使用它:

<your.package.name.ExtendedBottomNavigationView android:id="@id/bottomMenu" style="@style/bottomMenu"/>

【讨论】:

    【解决方案2】:

    在 res/font/ 文件夹中添加字体文件以将字体捆绑为资源

    然后

    您可以使用样式资源对其进行更改。 在您的styles.xml 中:

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

    然后将其作为主题应用到您的视图中:

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

    刚刚检查了我的应用程序,它运行良好。

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

    【讨论】:

    • 谢谢。此答案应标记为已接受。就我而言,我使用的是Calligraphy library,所以我的样式xml就像&lt;item name="fontPath"&gt;fonts/lato_medium.ttf&lt;/item&gt;
    • 请注意,如果您想更改文本的字体,您必须指定:name="fontFamily" 而不是 name="android:fontFamily"
    • 这个答案有效,但它也覆盖了默认动画
    【解决方案3】:
    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);
                            }
                        }
                    }
                }
            }
        }
    

    【讨论】:

      【解决方案4】:

      在您的布局中:

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

      在你的styles.xml中:

      <style name="BottomNavigationViewTextStyle">
          ...
          <item name="android:fontFamily">@font/whatever_font</item>
          ...
      </style>
      

      【讨论】:

      • 这比 A. Kazarovets 的回答要好,因为它不会覆盖和破坏动画
      • 仅供参考:这对我来说不适用于 android:fontFamily,仅适用于 fontFamily(相当于 app:fontFamily)
      • 很好的答案,它正在使用 Theme.MaterialComponents 样式
      【解决方案5】:

      如果您在“资产文件夹”中有自定义字体,并且您想在“底部导航”中设置,请使用此代码

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

      然后在你的 MainActivity 中使用 methode 像这样

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

      kotlin 版本

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

      祝你好运

      【讨论】:

      • 为什么要从 AppCompatActivity 扩展 Font 类?
      • @hassanmoradnezhad 我们需要上下文和视图,因此必须从 AppCompatActivity 扩展
      【解决方案6】:

      根据https://material.io/develop/android/components/bottom-navigation-view/,只需为 TextAppearance.MaterialComponents.Caption 样式设置一个 fontFamily 项,它就可以工作。 com.google.android.material.bottomnavigation.BottomNavigationView 默认会使用这个。

      只要知道其他依赖 TextAppearance.MaterialComponents.Caption 的组件也会发生变化,但这可能是可取的。

      <style name="TextAppearance.MaterialComponents.Caption" parent="AppMaterialComponentsTheme">
              <item name="fontFamily">@font/example</item>
      </style>
      

      【讨论】:

        【解决方案7】:

        自定义BottomNavigationView的Kotlin代码设置自定义字体:

        1.将字体保存到您的 android studio 项目的 assets 目录中。这里我使用了我的字体“SolaimanLipi_20-04-07.ttf”

        2.复制下面的kotlin代码并粘贴到你的android studio项目中。

        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.在xml文件上使用如下:

        <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 回答帮助:

        【讨论】:

          【解决方案8】:

          Kotlin 爱好者

          为自定义资产字体创建扩展类

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

          现在调用这个扩展

             navigationTextFont(yourNavigationViewId)
          

          祝你好运

          【讨论】:

            【解决方案9】:

            Kotlin 语言:

            1:使用自定义名称创建文件,例如:BottomNavigationViewExtension.kt

            2:把代码放在下面:

            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:用法:

            navView.changeNavTypeface(
                Typeface.createFromAsset(
                    assets,
                    "fonts/IRANSansMobile.ttf"
                )
            )
            

            【讨论】:

              【解决方案10】:

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

              【讨论】:

                【解决方案11】:

                长话短说:

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

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2020-04-29
                  • 1970-01-01
                  • 1970-01-01
                  • 2018-02-13
                  • 2016-06-20
                  • 2011-08-15
                  相关资源
                  最近更新 更多