Is there a way to do it?
Yes. The NavigationView
doesn't provide a direct way of handling this, but it can easily be achieved using View.findViewsWithText
.
There are two things that will help us handle this.
- Each
MenuItem
view is a TextView
. So, that makes applying your Typeface
that much easier. For more information on the TextView
actually used by NavigationView
, see NavigationMenuItemView
.
NavigationView
provides a callback when a MenuItem
is selected. We're going to have to supply each MenuItem
with a unique id and this callback will help generify those ids as much as possible, which means a little less code later on. Although, this is more related to whether or not you have a SubMenu
.
Implementation
Notice each MenuItem
id is simply menuItem+Position
. This will come in handy later when we're finding the View
for each MenuItem
.
<group android:checkableBehavior="single">
<item
android:id="@+id/menuItem1"
android:icon="@drawable/ic_dashboard"
android:title="MenuItem 1" />
<item
android:id="@+id/menuItem2"
android:icon="@drawable/ic_event"
android:title="MenuItem 2" />
<item
android:id="@+id/menuItem3"
android:icon="@drawable/ic_headset"
android:title="MenuItem 3" />
<item
android:id="@+id/menuItem4"
android:icon="@drawable/ic_forum"
android:title="MenuItem 4" />
</group>
<item android:title="Sub items" >
<menu>
<item
android:id="@+id/menuItem5"
android:icon="@drawable/ic_dashboard"
android:title="Sub item 5" />
<item
android:id="@+id/menuItem6"
android:icon="@drawable/ic_forum"
android:title="Sub item 6" />
</menu>
</item>
/** The total number of menu items in the {@link NavigationView} */
private static final int MENU_ITEMS = 6;
/** Contains the {@link MenuItem} views in the {@link NavigationView} */
private final ArrayList<View> mMenuItems = new ArrayList<>(MENU_ITEMS);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
final NavigationView navView = ...
// Grab the NavigationView Menu
final Menu navMenu = navView.getMenu();
// Install an OnGlobalLayoutListener and wait for the NavigationMenu to fully initialize
navView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
// Remember to remove the installed OnGlobalLayoutListener
navView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
// Loop through and find each MenuItem View
for (int i = 0, length = MENU_ITEMS; i < length; i++) {
final String id = "menuItem" + (i + 1);
final MenuItem item = navMenu.findItem(getResources().getIdentifier(id, "id", getPackageName()));
navView.findViewsWithText(mMenuItems, item.getTitle(), View.FIND_VIEWS_WITH_TEXT);
}
// Loop through each MenuItem View and apply your custom Typeface
for (final View menuItem : mMenuItems) {
((TextView) menuItem).setTypeface(yourTypeface, Typeface.BOLD);
}
}
});
}
You can see how using a generic MenuItem
id allows you to utilize Resources.getIdentifier
and save a few lines of code.
SubMenu
caveat
Something to keep in mind. You need to explicitly loop over your N
menu items rather than using Menu.size
. Otherwise, your SubMenu
items won't be recognized. In other words, if you don't have a SubMenu
, another way of doing this would be:
for (int i = 0, length = navMenu.size(); i < length; i++) {
final MenuItem item = navMenu.getItem(i);
navigationView.findViewsWithText(mMenuItems, item.getTitle(), View.FIND_VIEWS_WITH_TEXT);
}
And you don't have to worry about applying a unique id to each MenuItem
.
Results
The font I'm using in the example is: Smoothie Shoppe