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

Cuando creo un menú de opciones, los elementos parecen predeterminados a la fuente nativa "sans". Cuando miro las aplicaciones comerciales, en su mayoría parecen hacer lo mismo. ¿Es posible establecer el tamaño de fuente, el peso del color o la tipografía de los elementos del menú de opciones?

Gracias por adelantado.

Puede personalizar el menú de opciones, incluyendo:

  1. Añadir una fuente personalizada

  2. Cambia tamaño de fuente

  3. Cambiar el color de la fuente

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

Para cambiar el fondo a un borde o degradado tienes que crear una carpeta de recursos en res llamada drawable y, dentro de ella, crear el XML de borde o XML de degradado.

Todo esto puede hacerse mediante programación 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 se olvide de crear la carpeta llamada menu en la carpeta res , y dentro de la carpeta de menu crear un XML para su menú (por ejemplo, cool_menu.xml ), como esto:

 <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:title="about"android:id="@+id/AboutUs" /> <item android:title="Prefs" android:id="@+id/preferences" /> <item android:title="Exit" android:id="@+id/exit" /> </menu> 

Entonces la salida será algo como esto:

Introduzca aquí la descripción de la imagen

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

Busqué alrededor de un poco, y me enteré de que puede utilizar vistas personalizadas para los elementos del menú. Simplemente llame a setActionView en el elemento de 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 que tener un LinearLayout como elemento raíz). Por ejemplo, puede utilizar el diseño TextView + ImageView que @ R4j propone en su respuesta.

En mi caso de uso, simplemente coloco los objetos Button en el menú y luego confié en el manejador onButtonClick de los botones para responder a los eventos, de manera efectiva, paso a paso la necesidad de manejarlos en la actividad que contiene el menú.

(Gran pregunta, por cierto. Gracias !!)

En lugar de utilizar el recurso XML para el menú, infle el código utilizando menu.add y utilice SpannableString nuevo () para asignar una fuente personalizada.

Aquí hay un ejemplo de trabajo 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(...) se requiere para solucionar un error en la API android: cuando se selecciona un elemento de menú, se registra el evento y se utiliza el titleCondensed para escribir el registro. Si el titleCondensed no está definido utiliza el title y EventLog.writeEvent bloquea cada vez que la cadena de registro se formatea.

Por lo tanto, pasar una CharSequence no formada en el consendedTitle solución el error.

Probado y el trabajo 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 span personalizada

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

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

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" android:layout_gravity="center" android:padding="4dip" android:clickable="true" android:background="@drawable/custom_menu_selector"> <ImageView android:id="@+id/custom_menu_item_icon" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" android:paddingBottom="2dip" android:paddingTop="2dip"/> <TextView android:id="@+id/custom_menu_item_caption" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#ffffff" android:textSize="12sp" android:gravity="center"/> 

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

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Mi cuenta" android:id="@+id/buttonMyAccount" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Ayuda" android:id="@+id/buttonHelp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Contacto" android:id="@+id/buttonContact" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Acerca de" android:id="@+id/buttonAbout" /> </LinearLayout> 

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

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

Ninguna de las respuestas anteriores funcionó para mí. Lo logré mediante 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; } 
FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.