我想更改 PopupMenu 项的默认字体,并使用我的自定义字体。
这是我用于创建 PopupMenu :
的代码PopupMenu pm = new PopupMenu(this, v);
getMenuInflater().inflate(R.menu.main, pm.getMenu());
pm.show();
菜单项目:
<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>
如果您与我分享您的建议,我将非常感激: - )
此致
答案 0 :(得分:8)
检查我的解决方案是否存在同样的问题:
Popup Menu Mehthod:
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);
}
}
在此方法中应用您的字体,您也可以更改字体颜色:
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类:
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);
}
}
答案 1 :(得分:2)
你可以使用反射。它可用于弹出菜单项的任何自定义。 android支持中菜单项的资源布局在android.support.v7.internal.view.menu.MenuPopupHelper中定义,其字段名称为“ITEM_LAYOUT”,声明为static final;它的价值等于“R.layout.abc_popup_menu_item_layout” 我在Grepcode中找到布局文件并将其复制到我的项目布局目录中。我把它命名为popup_menu_item_layout.xml。我的弹出菜单项布局来到这里
<?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. -->
然后创建自定义类PopupMenuItemView:
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);
}
}
}
最后通过反射替换菜单项的布局资源ID;在您的主要活动onCreate方法或您的app onCreate方法中的某些地方:
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 :(得分:1)
我知道这是一个古老的问题,但是如果像我这样的人偶然发现了这个特定问题以寻找明确的答案,我仍然想回答。
不知道AppCompat
,但是在玩MaterialComponents
并发现了API textAppearanceLargePopupMenu
。例如,假设您要为应用程序中的所有PopupMenu
应用特定的字体,然后定义一个style
并将其应用于您的theme
:
示例样式:
<style name="AppTheme.TextAppearance.Popup" parent="TextAppearance.MaterialComponents.Caption">
<item name="fontFamily">@font/opensans_regular</item>
</style>
示例主题:
<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
<!-- All other attrs and styles -->
<item name="textAppearanceLargePopupMenu">@style/AppTheme.TextAppearance.Popup</item>
</style>
答案 3 :(得分:-1)
我认为这是不可能的。 实际上你可以使用popupWindow并根据需要自定义它。