Как установить настраиваемый шрифт для элементов в NavigationView?

С помощью нового NavigationView мы можем установить элементы ящика через ресурс меню в XML.

При этом мы можем установить каждый элемент с чем-то вроде

  

Но теперь я хочу установить собственный шрифт для каждого из этих элементов в моем ящике, и я не мог найти способ сделать это, либо XML, либо кодом Java. Есть ли способ сделать это?

просто добавьте следующий файл classа в ваш проект.

 import android.graphics.Paint; import android.graphics.Typeface; import android.text.TextPaint; import android.text.style.TypefaceSpan; public class CustomTypefaceSpan extends TypefaceSpan { private final Typeface newType; public CustomTypefaceSpan(String family, Typeface type) { super(family); newType = type; } @Override public void updateDrawState(TextPaint ds) { applyCustomTypeFace(ds, newType); } @Override public void updateMeasureState(TextPaint paint) { applyCustomTypeFace(paint, newType); } private static void applyCustomTypeFace(Paint paint, Typeface tf) { int oldStyle; Typeface old = paint.getTypeface(); if (old == null) { oldStyle = 0; } else { oldStyle = old.getStyle(); } int fake = oldStyle & ~tf.getStyle(); if ((fake & Typeface.BOLD) != 0) { paint.setFakeBoldText(true); } if ((fake & Typeface.ITALIC) != 0) { paint.setTextSkewX(-0.25f); } paint.setTypeface(tf); } } 

затем создайте следующий метод для своей деятельности

 private void applyFontToMenuItem(MenuItem mi) { Typeface font = Typeface.createFromAsset(getAssets(), "ds_digi_b.TTF"); SpannableString mNewTitle = new SpannableString(mi.getTitle()); mNewTitle.setSpan(new CustomTypefaceSpan("" , font), 0 , mNewTitle.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); mi.setTitle(mNewTitle); } 

и называть его активностью.

 navView = (NavigationView) findViewById(R.id.navView); Menu m = navView.getMenu(); for (int i=0;i0 ) { for (int j=0; j  

и вот мой вывод

введите описание изображения здесь

эта работа для меня

   

res-> с ценностно> стили

   

// для установки пользовательского шрифта MainApplication.java

 public class MainApplication extends Application { @Override public void onCreate() { super.onCreate(); //set Custom Typeface FontsOverride.setDefaultFont(this, "MONOSPACE", "OpenSans-Semibold.ttf"); } } 

// FontsOverride.java

 public final class FontsOverride { public static void setDefaultFont(Context context, String staticTypefaceFieldName, String fontAssetName) { final Typeface regular = Typeface.createFromAsset(context.getAssets(), fontAssetName); replaceFont(staticTypefaceFieldName, regular); } protected static void replaceFont(String staticTypefaceFieldName, final Typeface newTypeface) { try { final Field staticField = Typeface.class .getDeclaredField(staticTypefaceFieldName); staticField.setAccessible(true); staticField.set(null, newTypeface); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } } 

Есть ли способ сделать это?

Да. NavigationView не обеспечивает прямой способ обработки этого, но его можно легко достичь с помощью View.findViewsWithText .

Есть две вещи, которые помогут нам справиться с этим.

  1. Каждое представление MenuItem представляет собой TextView . Таким образом, это упрощает применение вашего Typeface . Дополнительные сведения о TextView фактически используемом NavigationView , см. В разделе NavigationMenuItemView .
  2. NavigationView обеспечивает обратный вызов при MenuItem . Нам нужно будет предоставить каждому MenuItem уникальный идентификатор, и этот обратный вызов поможет как можно больше генерировать эти идентификаторы, а это значит, что позже будет меньше кода. Хотя, это больше связано с тем, есть ли у вас SubMenu .

Реализация

Обратите внимание, что каждый идентификатор MenuItem – это просто menuItem+Position . Это будет полезно позже, когда мы найдем View для каждого MenuItem .

             


 /** The total number of menu items in the {@link NavigationView} */ private static final int MENU_ITEMS = 6; /** Contains the {@link MenuItem} views in the {@link NavigationView} */ private final ArrayList mMenuItems = new ArrayList<>(MENU_ITEMS); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... final NavigationView navView = ... // Grab the NavigationView Menu final Menu navMenu = navView.getMenu(); // Install an OnGlobalLayoutListener and wait for the NavigationMenu to fully initialize navView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { // Remember to remove the installed OnGlobalLayoutListener navView.getViewTreeObserver().removeOnGlobalLayoutListener(this); // Loop through and find each MenuItem View for (int i = 0, length = MENU_ITEMS; i < length; i++) { final String id = "menuItem" + (i + 1); final MenuItem item = navMenu.findItem(getResources().getIdentifier(id, "id", getPackageName())); navView.findViewsWithText(mMenuItems, item.getTitle(), View.FIND_VIEWS_WITH_TEXT); } // Loop through each MenuItem View and apply your custom Typeface for (final View menuItem : mMenuItems) { ((TextView) menuItem).setTypeface(yourTypeface, Typeface.BOLD); } } }); } 

Вы можете увидеть, как использование общего идентификатора MenuItem позволяет вам использовать Resources.getIdentifier и сохранять несколько строк кода.

SubMenu

Что-то нужно иметь в виду. Вам нужно явно Menu.size элементы меню N а не использовать Menu.size . В противном случае ваши элементы SubMenu не будут распознаны. Другими словами, если у вас нет SubMenu , другой способ сделать это:

 for (int i = 0, length = navMenu.size(); i < length; i++) { final MenuItem item = navMenu.getItem(i); navigationView.findViewsWithText(mMenuItems, item.getTitle(), View.FIND_VIEWS_WITH_TEXT); } 

И вам не нужно беспокоиться о применении уникального идентификатора к каждому MenuItem .

Результаты

Результаты

Шрифт, который я использую в примере: Smoothie Shoppe

Используйте свойство app: itemTextAppearance = “” . Надеюсь это поможет.

   

В styles.xml write

  

Я использовал приложение: тема

  

Styles.xml:

  

Не пользовательский шрифт, а другой способ изменить шрифт навигационных элементов. Создайте макет с именем design_navigation_item.xml .

  

Затем измените fontFamily на нужный шрифт.

Немного поздно ответить, но я нашел более чистый способ сделать это, поэтому хотел бы поделиться.

  • Сделать пользовательский вид NavFontTextView.java :

     import android.content.Context; import android.support.design.internal.NavigationMenuItemView; import android.util.AttributeSet; import utils.CustomFontHelper; public class NavFontTextView extends NavigationMenuItemView { Context mContext; public NavFontTextView(Context context) { super(context); mContext = context; setDefaultFont(); } public NavFontTextView(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; setDefaultFont(); CustomFontHelper.setCustomFont(this, context, attrs); } public NavFontTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mContext = context; setDefaultFont(); CustomFontHelper.setCustomFont(this, context, attrs); } public void setDefaultFont() { CustomFontHelper.setCustomFont(this, "fonts/SourceSansPro-Regular.ttf", mContext); } } 
  • Создайте файл CustomFontHelper.java :

     import android.content.Context; import android.content.res.TypedArray; import android.graphics.Typeface; import android.util.AttributeSet; import android.widget.TextView; /** * Taken from: http://stackoverflow.com/a/16648457/75579 */ public class CustomFontHelper { /** * Sets a font on a textview based on the custom com.my.package:font attribute * If the custom font attribute isn't found in the attributes nothing happens * @param textview * @param context * @param attrs */ public static void setCustomFont(TextView textview, Context context, AttributeSet attrs) { TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomFont); String font = a.getString(R.styleable.CustomFont_font); setCustomFont(textview, font, context); a.recycle(); } /** * Sets a font on a textview * @param textview * @param font * @param context */ public static void setCustomFont(TextView textview, String font, Context context) { if(font == null) { return; } Typeface tf = FontCache.get(font, context); if(tf != null) { textview.setTypeface(tf); } } } 
  • Сделайте макет layout/design_navigation_item.xml (имя должно быть точно таким же):

       
  • Поместите файл шрифта SourceSansPro-Bold.ttf по этому пути: app/src/main/assets/fonts/SourceSansPro-Bold.ttf

Тебе хорошо идти! Таким образом, вы можете очистить свою основную деятельность.

Вот скриншот: введите описание изображения здесь

для тех, кто использует ответ @Moinkhan, для применения шрифта к каждой части меню используйте это решение, и для каждого раздела заголовка используйте id. ваше меню вроде этого ..

      

и решение вроде этого ..

 navMenu = navView.getMenu(); MenuItem item= navView.getMenu().findItem(R.id.nav_others); applyFontToMenuItem(item); 

возможно, это помогает кому-то.

Мне очень понравилось решение «Дракона, который сплел огонь», но я не получил textview . Это можно сделать, выполнив следующие действия:

 TextView textView = (CheckedTextView) findViewById(android.support.design.R.id.design_menu_item_text); public class StyledMenuItem extends NavigationMenuItemView { public StyledMenuItem(Context context) { super(context); } public StyledMenuItem(Context context, AttributeSet attrs) { super(context, attrs); if (!isInEditMode()) { setCustomFont(context, attrs); setFilterTouchesWhenObscured(true); } } public StyledMenuItem(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); if (!isInEditMode()) { setCustomFont(context, attrs); setFilterTouchesWhenObscured(true); } } private void setCustomFont(Context ctx, AttributeSet attrs) { TypedArray a = ctx.obtainStyledAttributes(attrs, R.styleable.ProjectView); String customFont = a.getString(R.styleable.ProjectView_projectFont); setCustomFont(ctx, customFont); a.recycle(); } private void setCustomFont(Context ctx, String asset) { Typeface typeFace = TypeFaceProvider.getTypeFace(ctx, asset); TextView textView = (CheckedTextView) findViewById(android.support.design.R.id.design_menu_item_text); if (typeFace != null && textView != null) { textView.setTypeface(typeFace); } } 

design_navigation_item.xml:

  

style.xml:

  

attrs.xml:

       

Я отредактировал ответ @ adneal на это. Он перебирает элементы меню (не переходя в подпункты, только элементы верхнего уровня) в соответствии с индексом вместо идентификатора и устанавливает Typeface.

Замените rightNavigationView на ваш NavigationView и {TYPEFACE} с помощью нужного TypeFace

 final Menu navMenu = rightNavigationView.getMenu(); rightNavigationView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { ArrayList menuItems = new ArrayList<>(); // save Views in this array rightNavigationView.getViewTreeObserver().removeOnGlobalLayoutListener(this); // remove the global layout listener for (int i = 0; i < navMenu.size(); i++) {// loops over menu items to get the text view from each menu item final MenuItem item = navMenu.getItem(i); rightNavigationView.findViewsWithText(menuItems, item.getTitle(), View.FIND_VIEWS_WITH_TEXT); } for (final View menuItem : menuItems) {// loops over the saved views and sets the font ((TextView) menuItem).setTypeface({TYPE}, Typeface.BOLD); } } }); 

Другой способ настроить свой собственный шрифт:

1. Вы можете добавить свои шрифты в папку «font», а затем вы можете использовать их в любом TextView (или там, где вам нужно)

введите описание изображения здесь

Пример font.xml:

     

2. В вашем файле styles.xml вы можете настроить стиль текста элемента с этим шрифтом и цветом, где вам нужно (из ответа @Moonis Abidi)

   

3. Теперь вам нужно указать это только в своем навигационном представлении с помощью приложения: itemTextAppearance :

  

// ————- Также, если вам нужно использовать этот шрифт из других TextViews, вы можете использовать его как

   

Это другой подход:

В NavigationView есть дочерние объекты, называемые NavigationMenuItemView . В NavigationMenuItemView есть двое детей. Один из них – AppCompatCheckedTextView .

Переопределите метод onLayout для NavigationView, как показано ниже, и измените Typefase в AppCompatCheckedTextView:

 public final class NavigationViewWithCustomFont extends NavigationView{ private final Context context; private Typeface fontFace; public NavigationViewWithCustomFont(Context context, AttributeSet attrs){ super(context, attrs); this.context = context; this.fontFace = null; } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom){ super.onLayout(changed, left, top, right, bottom); final ViewGroup navMenuView = (ViewGroup)getChildAt(0); final int navMenuItemsCount = navMenuView.getChildCount(); ViewGroup itemView; if(fontFace == null){ fontFace = Typeface.createFromAsset(context.getAssets(), context.getString(R.string.BTrafficBold)); } for(int i=0; i 
 BottomNavigationView bottom_nav = findViewById(R.id.bottom_nav); Typeface font = Typeface.createFromAsset(getAssets(), "--your customized font file--"); for (int i = 0; i  
 applyFontToMenuItem(popup.getMenu().getItem(0)); private void applyFontToMenuItem(MenuItem mi) { Typeface font = Typeface.createFromAsset(getAssets(), "fonts/Redressed.ttf"); SpannableString mNewTitle = new SpannableString(mi.getTitle()); mNewTitle.setSpan(new CustomTypefaceSpan("", font), 0, mNewTitle.length(),pannable.SPAN_INCLUSIVE_INCLUSIVE); mi.setTitle(mNewTitle); } 
Давайте будем гением компьютера.