How to change the font PopupMenu

I want to change the default font of PopupMenu elements and use them from my custom font for them.

This is the code I used to create PopupMenu :

PopupMenu pm = new PopupMenu(this, v); getMenuInflater().inflate(R.menu.main, pm.getMenu()); pm.show(); 

And menu items:

 <menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/Setting" android:title="Setting"/> <item android:id="@+id/About" android:title="About"/> <item android:id="@+id/Help" android:title="Help"/> </menu> 

I will be so grateful if you share your suggestions with me :-)

Hi

+8
android popupmenu
source share
4 answers

Check out my solution for the same problem:

Popup Menu Method:

  private void showEditPopupWindow(Context mContext) { PopupMenu popupMenu = new PopupMenu(mContext, view); popupMenu.getMenuInflater().inflate(R.menu.YOUR_MENU, popupMenu.getMenu()); popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { if (item.getItemId() == R.id.delete) { // Do your stuffs; } else { // Do your stuffs } return true; } }); Menu menu = popupMenu.getMenu(); for (int i = 0; i < menu.size(); i++) { MenuItem mi = menu.getItem(i); applyFontToMenuItem(mi); } } 

Apply your font in this method, you can also change the font color:

 private void applyFontToMenuItem(MenuItem mi) { Typeface font = Typeface.createFromAsset(mContext.getAssets(), "fonts/YOUR_FONT.ttf"); SpannableString mNewTitle = new SpannableString(mi.getTitle()); mNewTitle.setSpan(new CustomTypeFaceSpan("", font,Color.WHITE), 0, mNewTitle.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); mi.setTitle(mNewTitle); } 

CustomTypeFaceSpan Class:

  public class CustomTypeFaceSpan extends TypefaceSpan { private final Typeface newType; private final int mColor; public CustomTypeFaceSpan(String family, Typeface type, @ColorInt int color) { super(family); newType = type; mColor = color; } @Override public void updateDrawState(TextPaint ds) { ds.setColor(mColor); applyCustomTypeFace(ds, newType); } @Override public void updateMeasureState(TextPaint paint) { applyCustomTypeFace(paint, newType); } @Override public int getSpanTypeId() { return super.getSpanTypeId(); } @ColorInt public int getForegroundColor() { return mColor; } 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); } } 
+5
source share

you can use reflection. It can be used for any setting of popup menu items. The layout of the resources for a menu item in android support is defined in the android.support.v7.internal.view.menu.MenuPopupHelper file, and this is the name of the field "ITEM_LAYOUT" declared as a static ending; This value is "R.layout.abc_popup_menu_item_layout" I found the layout file in Grepcode and copied it into my project layout directory. I called it popup_menu_item_layout.xml. The layout of the pop-up menu item is displayed here.

 <?xml version="1.0" encoding="utf-8"?> <mypackage.PopupMenuItemView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="?attr/dropdownListPreferredItemHeight" android:minWidth="196dip" android:paddingRight="16dip"> <!-- Icon will be inserted here. --> <!-- The title and summary have some gap between them, and this 'group' should be centered vertically. --> <RelativeLayout android:layout_width="0dip" android:layout_weight="1" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginLeft="16dip" android:duplicateParentState="true"> <TextView android:id="@+id/title" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" android:textAppearance="?attr/textAppearanceLargePopupMenu" android:singleLine="true" android:duplicateParentState="true" android:ellipsize="marquee" android:fadingEdge="horizontal"/> <TextView android:id="@+id/shortcut" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/title" android:layout_alignParentLeft="true" android:textAppearance="?attr/textAppearanceSmallPopupMenu" android:singleLine="true" android:duplicateParentState="true"/> </RelativeLayout> <!-- Checkbox, and/or radio button will be inserted here. --> 

Then create your own PopupMenuItemView class:

 public class PopupMenuItemView extends android.support.v7.internal.view.menu.ListMenuItemView { public PopupMenuItemView(Context context, AttributeSet attrs) { super(context, attrs); } public PopupMenuItemView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onFinishInflate() { super.onFinishInflate(); applyTypefaceToAll(this, your_typeface); TypefaceUtils.applyTextSizeToAll(this, your_textsize); } public static void applyTypefaceToAll(View view, Typeface typeface) { if (view instanceof ViewGroup) { ViewGroup viewGroup = (ViewGroup) view; for (int childIndex = 0; childIndex < viewGroup.getChildCount(); childIndex++) applyTypefaceToAll(viewGroup.getChildAt(childIndex), typeface); } else if (view instanceof TextView) { TextView textView = (TextView) view; textView.setTypeface(typeface); textView.setPaintFlags(textView.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG | Paint.DEV_KERN_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG); } } public static void applyTextSizeToAll(View view, float size) { if (view instanceof ViewGroup) { ViewGroup viewGroup = (ViewGroup) view; for (int childIndex = 0; childIndex < viewGroup.getChildCount(); childIndex++) applyTextSizeToAll(viewGroup.getChildAt(childIndex), size); } else if (view instanceof TextView) { TextView textView = (TextView) view; textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, size); textView.setPaintFlags(textView.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG | Paint.DEV_KERN_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG); } } } 

Finally, replace the layout resource identifier for the menu items by reflection; some where, as in your main action onCreate method or in your application onCreate method:

  try { setFinalStatic(MenuPopupHelper.class.getDeclaredField("ITEM_LAYOUT"), R.layout.popup_menu_item_layout); } catch (Exception e) { e.printStackTrace(); } public static void setFinalStatic(Field field, Object newValue) throws Exception { field.setAccessible(true); try { Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); }catch (Exception e) { e.printStackTrace(); } field.set(null, newValue); } 
+2
source share

I think it's impossible. In fact, you can use popupWindow and configure it as a menu as you want.

0
source share

I know this is an old question, but still want to answer if someone like me stumbles on this particular question in search of a specific answer.

I don’t know about AppCompat , but I played with MaterialComponents and found out textAppearanceLargePopupMenu API textAppearanceLargePopupMenu . For example, suppose you want to apply a specific font to all PopupMenu in your application, then define a style and apply it to your theme :

Style example:

 <style name="AppTheme.TextAppearance.Popup" parent="TextAppearance.MaterialComponents.Caption"> <item name="fontFamily">@font/opensans_regular</item> </style> 

Example topic:

 <style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar"> <!-- All other attrs and styles --> <item name="textAppearanceLargePopupMenu">@style/AppTheme.TextAppearance.Popup</item> </style> 
0
source share

All Articles