¿Cómo puedo usar TypefaceSpan o StyleSpan con una tipografía personalizada?

No he encontrado una manera de hacer esto. ¿Es posible?

Bueno, no pude encontrar la forma de hacerlo con las clases disponibles, así que extendí el TypefaceSpan por mi cuenta y ahora funciona para mí. Aquí esta lo que hice:

 package de.myproject.text.style; 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); } } 

Mientras que el notme tiene esencialmente la idea correcta, la solución dada es un poco hacky ya que la “familia” se vuelve redundante. También es ligeramente incorrecto porque TypefaceSpan es uno de los tramos especiales que Android conoce y espera cierto comportamiento con respecto a la interfaz ParcelableSpan (cuya subclase notme no es adecuada, ni es posible implementarla).

Una solución más simple y más precisa sería:

 public class CustomTypefaceSpan extends MetricAffectingSpan { private final Typeface typeface; public CustomTypefaceSpan(final Typeface typeface) { this.typeface = typeface; } @Override public void updateDrawState(final TextPaint drawState) { apply(drawState); } @Override public void updateMeasureState(final TextPaint paint) { apply(paint); } private void apply(final Paint paint) { final Typeface oldTypeface = paint.getTypeface(); final int oldStyle = oldTypeface != null ? oldTypeface.getStyle() : 0; final int fakeStyle = oldStyle & ~typeface.getStyle(); if ((fakeStyle & Typeface.BOLD) != 0) { paint.setFakeBoldText(true); } if ((fakeStyle & Typeface.ITALIC) != 0) { paint.setTextSkewX(-0.25f); } paint.setTypeface(typeface); } } 

En Android P es posible usar la misma clase TypefaceSpan que conoces, como se muestra aquí .

Pero en versiones anteriores, puedes usar lo que han mostrado más adelante en el video, sobre el cual he escrito aquí .

He intentado varias soluciones similares, encontré que esto es simple y viable. El hecho de que el elemento haga clic en el botón es manejar como un clic de botón en lugar de onOptionsItemSelected. ¡Gracias!

Aquí está mi código para mi proyecto:

En mi menu_main.xml:

     

En Mi MainActivity.java:

 @Override public boolean onCreateOptionsMenu(Menu menu) { //Use custom menu MenuInflater inflater = getMenuInflater(); //Inflate the custom menu inflater.inflate(R.menu.menu_main, menu); //reference to the item of the menu MenuItem i=menu.findItem(R.id.action_friends); Button itemuser =(Button) i.getActionView(); if(itemuser!=null){ // Create Typeface object to use unicode font in assets folder Typeface a = Typeface.createFromAsset(getApplicationContext(), "fontawesome-webfont.ttf"); // Set unicode font to menu item itemuser.setTypeface(a); itemuser.setText(getString(R.string.fa_users)); // Set item text and color itemuser.setTextColor(Color.BLACK); // Make item background transparent itemuser.setBackgroundColor(Color.TRANSPARENT); itemuser.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { //set action when clicked } }); } return super.onCreateOptionsMenu(menu); }