如何更改 Android 菜单项的自定义字体?
Posted
技术标签:
【中文标题】如何更改 Android 菜单项的自定义字体?【英文标题】:How to change Custom Font of Android Menu Item? 【发布时间】:2014-03-23 10:42:06 【问题描述】:我有以下 android Java 和 XML 代码。我想更改我的应用程序菜单项的字体。我只知道我们可以使用 setTypeface 更改 TextView 的字体,但无论如何都找不到菜单项。
JAVA代码-:
@Override
public boolean onCreateOptionsMenu(Menu menu)
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return true;
@Override
public boolean onOptionsItemSelected(MenuItem item)
switch (item.getItemId())
case R.id.action_refresh1:
Toast.makeText(this, "Item1 Selected", Toast.LENGTH_SHORT)
.show();
break;
case R.id.action_refresh2:
Toast.makeText(this, "Item2 Selected", Toast.LENGTH_SHORT)
.show();
break;
default:
break;
XML 代码-:
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/action_refresh1"
android:orderInCategory="100"
android:showAsAction="always"
android:title="Item1"/>
<item
android:id="@+id/action_refresh2"
android:orderInCategory="100"
android:showAsAction="always"
android:title="Item2"/>
</menu>
我想改变两个菜单项的字体,但不知道如何为菜单项集成settypface。
【问题讨论】:
也许这会给你一个提示 :) 请看下面的答案 :) ***.com/questions/4135699/… 【参考方案1】:您必须为菜单项提供自定义布局。
首先,在您的菜单 XML 中设置以下之一
CASE 1如果您使用的是支持库:
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_save"
android:title="@string/action_save"
android:icon="@drawable/ic_action_save"
android:orderInCategory="100"
app:showAsAction="always"
app:actionLayout="@layout/layout_menu_save"/>
</menu>
CASE 2如果您不使用支持库:
<menu
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_save"
android:title="@string/action_save"
android:icon="@drawable/ic_action_save"
android:orderInCategory="100"
android:showAsAction="always"
android:actionLayout="@layout/layout_menu_save"/>
</menu>
然后在actionLayout(在我的例子中是layout_menu_save.xml)写下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_
android:layout_
android:background="@drawable/background_transparent_stateful">
<com.example.YourCustomTypefaceTextView
android:layout_
android:layout_
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:gravity="center_vertical"
android:text="@string/action_save"/>
<ImageView
android:layout_
android:layout_
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:gravity="center_vertical"
android:src="@drawable/ic_action_save"
android:contentDescription="@string/action_save"/>
</LinearLayout>
背景可绘制对象 (background_transparent_stateful) 对于自定义布局的触摸反馈非常有用:
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_pressed="true"
android:drawable="#20FFFFFF">
</item>
<item
android:drawable="@android:color/transparent">
</item>
</selector>
这样,您将在左侧有一个带有自定义字体的文本作为右侧带有图标的标签。
显然您可以根据需要自定义布局!
编辑: 如果您使用支持库并且您的活动主题扩展了 AppCompatTheme,您可以获得典型的棒棒糖“波纹效果”以获得更好看的触摸反馈。 只需将自定义背景替换为:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_
android:layout_
android:background="?attr/selectableItemBackgroundBorderless">
...
</LinearLayout>
【讨论】:
嗯。这种工作,但不是真的(至少在 L 上)。您需要将您的 item.setOnMenuItemClickListener() 更改为 item.getActionView().setOnClickListener(),并使您的 LinearLayout 可点击和聚焦以注册点击。此外,涟漪效果在制作动画后会卡住。 嗨@EduardK。感谢您的反馈!这可能是一个错误,我在某些特定的 Activity 配置上遇到了类似的行为。您在使用 Android 支持库吗? 是的,使用支持库。看来我刚刚修好了。只需在 LinearLayout 中添加 clickable="true" 和 focusable="true" 即可。然后,涟漪效应和点击都正常工作。 (不要添加focusableInTouchMode) 感谢您的修复。我会立即更新答案!【参考方案2】:在styles.xml 中创建样式
<style name="Style_TextView">
<item name="fontFamily">@font/myriadproregular</item>
</style>
将以下代码添加到 android.support.design.widget.NavigationView
app:itemTextAppearance="@style/Style_TextView"
注意:它适用于 android.support.design.widget.NavigationView
【讨论】:
谢谢你,我一直在寻找几个小时前 28 的答案【参考方案3】:只需将您选择的字体添加到您的基本应用程序主题中。请注意,这会使所选字体成为任何未指定字体属性的基本字体。
<item name="android:fontFamily">@font/your_font</item>
【讨论】:
请记住,如果您有 values-21 文件夹,那么您也可以在那里进行此更改【参考方案4】:XML
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_edit"
android:title="@string/edit"
android:visible="true"
app:showAsAction="always" />
</menu>
在活动中或在片段中
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
Typeface face = Typeface.createFromAsset(getActivity().getAssets(),"fonts/OpenSans-Regular.ttf"); // THIS
TypefaceSpan face = new TypefaceSpan("<REPLACE_WITH_FONT_NAME>"); // OR THIS
SpannableStringBuilder title = new SpannableStringBuilder(getContext().getString(R.string.edit));
title.setSpan(face, 0, title.length(), 0);
menu.add(Menu.NONE, R.id.action_edit, 0, title); // THIS
MenuItem menuItem = menu.findItem(R.id.action_edit); // OR THIS
menuItem.setTitle(title);
super.onCreateOptionsMenu(menu, inflater);
【讨论】:
恕我直言,为菜单项设置自定义字体的最佳方式。 如果我想将下载的 ttf 文件设置为 TypefaceSpan?【参考方案5】:当您添加带有TypefaceSpan
的菜单项时,您也可以使用SpannableStringBuilder
。对每个菜单项执行类似的操作
TypefaceSpan span = new TypefaceSpan("<REPLACE_WITH_FONT_NAME>");
SpannableStringBuilder title = new SpannableStringBuilder("My Menu Item Title");
title.setSpan(span, 0, title.length(), 0);
menu.add(Menu.NONE, id, index, title);
【讨论】:
【参考方案6】:如果您的应用只需要在 Android Pie(API 级别 28)及更高版本上运行,您可以从 Typeface 中构造一个 TypefaceSpan onPrepareOptionsMenu。否则,您可以使用类似answer 建议的 CustomTypefaceSpan 类:
public boolean onPrepareOptionsMenu(Menu menu)
int customFontId = R.font.metropolis_medium;
for (int i = 0; i < menu.size(); i++)
MenuItem menuItem = menu.getItem(i);
String menuTitle = menuItem.getTitle().toString();
Typeface typeface = ResourcesCompat.getFont(this, customFontId);
SpannableString spannableString = new SpannableString(menuTitle);
// For demonstration purposes only, if you need to support < API 28 just use the CustomTypefaceSpan class only.
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P)
TypefaceSpan typefaceSpan = typeface != null ?
new TypefaceSpan(typeface) :
new TypefaceSpan("sans-serif");
spannableString.setSpan(typefaceSpan, 0, menuTitle.length(),
Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
else
CustomTypefaceSpan customTypefaceSpan = typeface != null ?
new CustomTypefaceSpan(typeface) :
new CustomTypefaceSpan(Typeface.defaultFromStyle(Typeface.NORMAL));
spannableString.setSpan(customTypefaceSpan, 0, menuTitle.length(),
Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
menuItem.setTitle(spannableString);
return true;
main.menu.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/settings"
android:onClick="openSettings"
android:title="@string/settings"
app:showAsAction="never" />
<item
android:id="@+id/about"
android:onClick="openAbout"
android:title="@string/about"
app:showAsAction="never" />
</menu>
之前和之后:
【讨论】:
删除了我在similar question 中的答案,因为这个问题似乎更相关。【参考方案7】:我发现这个解决方案对我很有用。希望它能帮助全新的冲浪者。
你的菜单main.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<item android:id="@+id/item1"
android:title="User"
android:orderInCategory="100"
android:visible="true"
app:showAsAction="always"
app:actionViewClass="android.widget.Button"
/>
</menu>
膨胀自定义菜单后,您可以对菜单项进行引用。当您获得对菜单项的引用时,您将能够自定义该项目以显示图标和 Unicode 文本。您的图标图像文件必须存储在
res/drawable 文件夹。
@Override
public boolean onCreateOptionsMenu(Menu menu)
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
//reference to the item of the menu
MenuItem i=menu.findItem(R.id.item1);
Button button_menu =(Button) i.getActionView();
if(itemuser!=null)
// Create Typeface object to use unicode font in assets folder
Typeface font= Typeface.createFromAsset(getApplicationContext().getAssets(),"fonts/arial.ttf");
// Set unicode font to menu item
button_menu .setTypeface(font);
// Set item text and color
button_menu .setText(getResources().getString(R.string._text));
button_menu .setTextColor(Color.WHITE);
// Make item background transparent
button_menu .setBackgroundColor(Color.TRANSPARENT);
// Show icon next to the text
Drawable icon=getApplicationContext().getResources().getDrawable( R.drawable.user);
button_menu .setCompoundDrawablesWithIntrinsicBounds( icon, null, null, null );
return true;
【讨论】:
【参考方案8】:只需将 NavigationView 的 itemTextAppearance 属性设置为系统或自定义样式:
<android.support.design.widget.NavigationView
android:id="@+id/nav_view"
android:layout_
android:layout_
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="@layout/nav_header_main_navigation"
app:itemBackground="@color/white"
app:itemTextAppearance="@style/TextAppearance.AppCompat"
app:itemTextColor="@color/saintpatrickblue"
app:menu="@menu/activity_main_navigation_drawer"/>
【讨论】:
这行得通。 textAppearance 应该是样式而不是字体。我犯了使用字体而不是样式的错误。 +1 先生【参考方案9】:@brahmyadigopula 的回答效果很好。
为了简单起见,这里只是一个更完整的版本:
菜单
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<item
android:id="@+id/update"
android:showAsAction="always"
android:title="@string/menu_update"
tools:ignore="UnusedAttribute"
android:actionViewClass="android.widget.Button"/>
</menu>
在您的 Activity 或 Fragment 中:
// Inflater the menu based on the layout above
inflater.inflate(menuRes, menu);
// Set font type face
if (setCustomFontType)
final MenuItem menuItem = menu.findItem(R.id.update);
String title = menuItem.getTitle().toString();
Button button_menu = (Button) menuItem.getActionView();
button_menu.setTypeface("<REPLACE_WITH_FONT_NAME>");
button_menu.setText(title);
button_menu.setTextColor(Color.WHITE);
button_menu.setBackgroundColor(_getResources().getColor(R.color.transparent_color));
button_menu.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
onOptionsItemSelected(menuItem);
);
super.onCreateOptionsMenu(menu, inflater);
【讨论】:
【参考方案10】:如果你使用的是 android.support.design 库,那么
app:itemTextAppearance="@style/bottom_navigation_textappreance"
以上都可以,但如果您使用的是 Material design,那么下面的属性就可以了
app:itemTextAppearanceActive="@style/bottom_navigation_textappreance"
app:itemTextAppearanceInactive="@style/bottom_navigation_textappreance"
<style name="bottom_navigation_textappreance"
parent="Widget.Design.BottomNavigationView">
<item name="fontFamily">@font/fira_sans_bold</item>
</style>
【讨论】:
以上是关于如何更改 Android 菜单项的自定义字体?的主要内容,如果未能解决你的问题,请参考以下文章