¿Cómo establecer una tipografía personalizada para los elementos en NavigationView?

Con el nuevo NavigationView , podemos configurar los elementos de un cajón a través de un recurso de menú en XML.

Con eso, podemos configurar cada elemento con algo como

  

Pero ahora, quiero establecer un tipo de letra personalizado para cada uno de esos elementos en mi cajón, y no pude encontrar una manera de hacerlo, ya sea por XML o por código de Java. ¿Hay una manera de hacerlo?

solo agregue el siguiente archivo de clase a su proyecto.

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

luego crea el siguiente método para tu actividad

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

y llamarlo de la actividad.

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

y aquí está mi salida

enter image description here

este trabajando para mi

   

res-> valores-> estilos

   

// para establecer Custom Typeface 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(); } } } 

¿Hay una manera de hacerlo?

Sí. NavigationView no proporciona una forma directa de manejar esto, pero se puede lograr fácilmente usando View.findViewsWithText .

Hay dos cosas que nos ayudarán a manejar esto.

  1. Cada vista de MenuItem es una vista de TextView . Entonces, eso hace que aplicar tu Typeface sea ​​mucho más fácil. Para obtener más información sobre el TextView realmente utilizado por NavigationView , vea NavigationMenuItemView .
  2. NavigationView proporciona una callback cuando se selecciona un elemento de MenuItem . Vamos a tener que proporcionar a cada MenuItem una identificación única y esta callback ayudará a generar esos identificadores tanto como sea posible, lo que significa un poco menos de código más adelante. Aunque, esto está más relacionado con si tienes o no un SubMenu .

Implementación

Observe que cada ID de MenuItem es simplemente menuItem+Position . Esto será útil más adelante cuando encontremos la View para cada elemento de 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); } } }); } 

Puede ver cómo el uso de una identificación genérica de MenuItem permite utilizar Resources.getIdentifier y guardar algunas líneas de código.

SubMenu advertencia

Algo para tener en cuenta. Necesitas hacer un bucle explícito sobre tus elementos del menú N lugar de utilizar Menu.size . De lo contrario, sus elementos SubMenu no serán reconocidos. En otras palabras, si no tiene un SubMenu , otra forma de hacerlo sería:

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

Y no tiene que preocuparse por aplicar una identificación única a cada elemento de MenuItem .

Resultados

resultados

La fuente que estoy usando en el ejemplo es: Smoothie Shoppe

Use la aplicación: itemTextAppearance = “” . Espero que esto ayude.

   

En styles.xml write

  

He usado la aplicación: tema

  

Styles.xml:

  

No es una tipografía personalizada, sino otra forma de cambiar la fuente de los elementos de navegación. Crea un diseño llamado design_navigation_item.xml .

  

A continuación, cambie fontFamily a la fuente deseada.

Es un poco tarde para responder, pero encontré una manera más limpia de hacerlo, así que me gustaría compartirlo.

  • Cree una vista personalizada 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); } } 
  • Crea un archivo llamado 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); } } } 
  • Realice un diseño de layout/design_navigation_item.xml (el nombre debe ser exactamente el mismo):

       
  • Coloque su archivo fuente SourceSansPro-Bold.ttf en esta ruta: app/src/main/assets/fonts/SourceSansPro-Bold.ttf

¡Eres bueno para ir! De esta forma, puedes mantener tu actividad principal más limpia.

Aquí hay una captura de pantalla: enter image description here

para aquellos que usan la respuesta de @Moinkhan, para aplicar la fuente a cada parte de los menús use esa solución y para cada sección de encabezado use id. su menú como este ..

      

y una solución como esta …

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

tal vez ayuda a alguien

Realmente me encantó la solución de “Dragón que escupe fuego” pero no textview la vista de textview . Esto podría hacerse haciendo lo siguiente:

 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:

       

He refactorizado la respuesta de @ adneal a esto. Pasa por los elementos del menú (sin entrar en elementos secundarios, solo elementos de nivel superior) de acuerdo con el índice en lugar de la identificación y establece la Tipografía.

Reemplace rightNavigationView con su NavigationView y {TYPEFACE} con su TypeFace deseado

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

Una forma diferente de configurar tu fuente personalizada:

1. Puede agregar sus fonts en una carpeta de “fonts”, y luego puede usarlas en cualquier TextView (o donde sea que necesite)

enter image description here

Un ejemplo de font.xml:

     

2. En su archivo styles.xml, puede personalizar el estilo de texto de su artículo con esa fuente y color, donde sea que lo necesite (de la respuesta de @Moonis Abidi)

   

3. Ahora, solo tiene que especificar esto en su vista de navegación con la aplicación: itemTextAppearance :

  

// ————- Además, si necesita usar esta fuente de otras TextViews, puede usarla como

   

Este es otro enfoque:

Un NavigationView tiene hijos llamados NavigationMenuItemView . Un NavigationMenuItemView tiene dos hijos. Uno es AppCompatCheckedTextView .

Anula el método de encendido de NavigationView como a continuación y cambia Typefase de 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); }