¿Cómo configurar una fuente para el menú de Opciones?

Cuando creo un menú de opciones, los elementos parecen predeterminados a la fuente nativa “sans”. Cuando miro aplicaciones comerciales, en su mayoría parecen hacer lo mismo. ¿Es posible establecer el tamaño de fuente, el grosor del color o el tipo de letra para los elementos del menú de opciones?

Gracias por adelantado.

Puede personalizar el menú de opciones, que incluye:

  1. Agrega una fuente personalizada

  2. Cambia tamaño de fuente

  3. Cambiar el color de la fuente

  4. Establecer el fondo de un recurso Drawable (por ejemplo, imagen, borde, degradado)

Para cambiar el fondo a un borde o gradiente, debe crear una carpeta de recursos en res denominada drawable y, dentro de ella, crear el borde XML o el gradiente XML.

Todo esto puede hacerse programáticamente como se muestra a continuación:

 public class CustomMenu extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } public boolean onCreateOptionsMenu(android.view.Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.cool_menu, menu); getLayoutInflater().setFactory(new Factory() { public View onCreateView(String name, Context context, AttributeSet attrs) { if (name.equalsIgnoreCase( "com.android.internal.view.menu.IconMenuItemView")) { try { LayoutInflater li = LayoutInflater.from(context); final View view = li.createView(name, null, attrs); new Handler().post(new Runnable() { public void run() { // set the background drawable if you want that //or keep it default -- either an image, border //gradient, drawable, etc. view.setBackgroundResource(R.drawable.myimage); ((TextView) view).setTextSize(20); // set the text color Typeface face = Typeface.createFromAsset( getAssets(),"OldeEnglish.ttf"); ((TextView) view).setTypeface(face); ((TextView) view).setTextColor(Color.RED); } }); return view; } catch (InflateException e) { //Handle any inflation exception here } catch (ClassNotFoundException e) { //Handle any ClassNotFoundException here } } return null; } }); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.AboutUs: Intent i = new Intent("com.test.demo.ABOUT"); startActivity(i); break; case R.id.preferences: Intent p = new Intent("com.test.demo.PREFS"); startActivity(p); break; case R.id.exit: finish(); break; } return false; } } 

No te olvides de crear una carpeta llamada menu en la carpeta res , y dentro de la carpeta del menu crea un XML para tu menú (por ejemplo, cool_menu.xml ) como este:

       

Entonces la salida será algo como esto:

enter image description here

@ Android Stack, cuando leí tu respuesta comencé a entrar en pánico pensando que tendría que usar una “fábrica”.

Busqué un poco y descubrí que puedes usar vistas personalizadas para los elementos del menú. Simplemente llame a setActionView en el elemento del menú.

 @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); // Inflate the menu items for use in the action bar MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.my_menu, menu); // Get the root inflator. LayoutInflater baseInflater = (LayoutInflater)getBaseContext() .getSystemService(Context.LAYOUT_INFLATER_SERVICE); // Inflate your custom view. View myCustomView = baseInflater.inflate(R.layout.my_custom_view, null); menu.findItem(R.id.my_custom_menu_icon).setActionView(myCustomView); // If myCustomView has additional children, you might have to inflate them separately here. // In my case, I used buttons in my custom view, and registered onClick listeners at this point. } 

Su implementación de my_custom_view puede ser cualquier vista que desee (aunque podría tener un LinearLayout como elemento raíz). Por ejemplo, puede usar el diseño de TextView + ImageView que @ R4j propone en su respuesta.

En mi caso de uso, simplemente coloque objetos de Button en el menú, y luego confié en el controlador onButtonClick de los botones para responder a los eventos, lo que hace que onButtonClick de lado la necesidad de manejarlos en la actividad que contiene el menú.

(Gran pregunta, por cierto, ¡¡¡Gracias !!)

En lugar de usar el recurso XML para el menú, inflarlo desde el código usando menu.add y usar el nuevo SpannableString () para asignar una fuente personalizada.

Aquí hay un ejemplo que funciona en Android 4.x:

 @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { ... menu.add(Menu.NONE,1234,1,wrapInSpan(getResources().getString(R.string.item_title))) .setTitleCondensed(getResources().getString(R.string.item_title)); ... } private CharSequence wrapInSpan(CharSequence value) { SpannableStringBuilder sb = new SpannableStringBuilder(value); sb.setSpan(MY_TYPEFACE, 0, value.length(), 0); return sb; } 

El setTitleCondensed(...) es necesario para solucionar un error en la API de Android: cuando se selecciona un elemento del menú, el evento se registra y utiliza el titleCondensed para escribir el registro. Si el titleCondensed no está definido, use el title y EventLog.writeEvent bloquea siempre que se formatee la cadena para el registro.

Así que pasar una CharSequence no formateada en la solución consendedTitle del error.

Probado y funciona como encanto 🙂

 @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.menu_feedback_filter, menu); for (int i = 0; i < menu.size(); i++) { MenuItem mi = menu.getItem(i); //for aapplying a font to subMenu ... SubMenu subMenu = mi.getSubMenu(); if (subMenu != null && subMenu.size() > 0) { for (int j = 0; j < subMenu.size(); j++) { MenuItem subMenuItem = subMenu.getItem(j); applyFontToMenuItem(subMenuItem, typeface); } } //the method we have create in activity applyFontToMenuItem(mi, typeface); } return super.onCreateOptionsMenu(menu); } private void applyFontToMenuItem(MenuItem mi, Typeface font) { SpannableString mNewTitle = new SpannableString(mi.getTitle()); mNewTitle.setSpan(new CustomTypefaceSpan("", font), 0, mNewTitle.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); mi.setTitle(mNewTitle); } 

Clase de tramo personalizado

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

Ninguna de las respuestas anteriores funcionó para mí. Lo logré siguiendo la siguiente solución:

 public boolean onPrepareOptionsMenu(Menu menu) { MenuItem item = menu.findItem(R.id.menu_name); item.setTitle(someTextToDisplayOnMenu); SpannableString spanString = new SpannableString(item.getTitle().toString()); spanString.setSpan(new TextAppearanceSpan(context,android.R.style.TextAppearance_Medium), 0,spanString.length(), 0); spanString.setSpan(new ForegroundColorSpan(Color.WHITE), 0, spanString.length(), 0); //fix the color to white item.setTitle(spanString); return true; } 

Creo que Android no admite la personalización para el menú de opciones. Pero puede intentarlo de otra forma: http://www.codeproject.com/Articles/173121/Android-Menus-My-Way
De esta manera, en realidad, el elemento del menú es una vista de texto y una vista de imagen, por lo que puede cambiar fácilmente la fuente, el color …

     

La única solución que encontré fue crear un cuadro de diálogo personalizado que aparece al presionar el botón de menú. El diseño sería así:

        

Después de eso, de la clase Activity, en el método ‘OnOptionsItemSelected’ escribo el siguiente código:

 @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_settings: Dialog dialog = new Dialog(this); dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); dialog.setContentView(R.layout.options_menu); dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT)); dialog.show(); Button buttonMyAccount = (Button) dialog.findViewById(R.id.buttonMyAccount); Typeface font = Typeface.createFromAsset(this.getAssets(), "SamsungIF_Rg.ttf"); buttonMyAccount.setTypeface(font); buttonMyAccount.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent itMyAccount = new Intent(getBaseContext(), AccountActivity.class); startActivity(itMyAccount); } }); Button buttonHelp = (Button) dialog.findViewById(R.id.buttonHelp); buttonHelp.setTypeface(font); buttonHelp.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent itAssistant = new Intent(getBaseContext(), AssistantPagerActivity.class); startActivity(itAssistant); } }); Button buttonContact = (Button) dialog.findViewById(R.id.buttonContact); buttonContact.setTypeface(font); buttonContact.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent itContact = new Intent(getBaseContext(), ContactActivity.class); startActivity(itContact); } }); Button buttonAbout = (Button) dialog.findViewById(R.id.buttonAbout); buttonAbout.setTypeface(font); buttonAbout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent itAbout = new Intent(getBaseContext(), AboutActivity.class); startActivity(itAbout); } }); Window window = dialog.getWindow(); WindowManager.LayoutParams wlp = window.getAttributes(); wlp.gravity = Gravity.RIGHT | Gravity.TOP; wlp.y = getSupportActionBar().getHeight(); wlp.width = 300; wlp.flags &= ~WindowManager.LayoutParams.FLAG_DIM_BEHIND; window.setAttributes(wlp); return true; default: return super.onOptionsItemSelected(item); } }