• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.support.design.internal;
18 
19 import android.content.Context;
20 import android.content.res.ColorStateList;
21 import android.content.res.Resources;
22 import android.graphics.drawable.Drawable;
23 import android.os.Build;
24 import android.os.Bundle;
25 import android.os.Parcelable;
26 import android.support.annotation.LayoutRes;
27 import android.support.annotation.NonNull;
28 import android.support.annotation.Nullable;
29 import android.support.annotation.StyleRes;
30 import android.support.design.R;
31 import android.support.v4.view.ViewCompat;
32 import android.support.v4.view.WindowInsetsCompat;
33 import android.support.v7.view.menu.MenuBuilder;
34 import android.support.v7.view.menu.MenuItemImpl;
35 import android.support.v7.view.menu.MenuPresenter;
36 import android.support.v7.view.menu.MenuView;
37 import android.support.v7.view.menu.SubMenuBuilder;
38 import android.support.v7.widget.RecyclerView;
39 import android.util.SparseArray;
40 import android.view.LayoutInflater;
41 import android.view.SubMenu;
42 import android.view.View;
43 import android.view.ViewGroup;
44 import android.widget.LinearLayout;
45 import android.widget.TextView;
46 
47 import java.util.ArrayList;
48 
49 /**
50  * @hide
51  */
52 public class NavigationMenuPresenter implements MenuPresenter {
53 
54     private static final String STATE_HIERARCHY = "android:menu:list";
55     private static final String STATE_ADAPTER = "android:menu:adapter";
56 
57     private NavigationMenuView mMenuView;
58     private LinearLayout mHeaderLayout;
59 
60     private Callback mCallback;
61     private MenuBuilder mMenu;
62     private int mId;
63 
64     private NavigationMenuAdapter mAdapter;
65     private LayoutInflater mLayoutInflater;
66 
67     private int mTextAppearance;
68     private boolean mTextAppearanceSet;
69     private ColorStateList mTextColor;
70     private ColorStateList mIconTintList;
71     private Drawable mItemBackground;
72 
73     /**
74      * Padding to be inserted at the top of the list to avoid the first menu item
75      * from being placed underneath the status bar.
76      */
77     private int mPaddingTopDefault;
78 
79     /**
80      * Padding for separators between items
81      */
82     private int mPaddingSeparator;
83 
84     @Override
initForMenu(Context context, MenuBuilder menu)85     public void initForMenu(Context context, MenuBuilder menu) {
86         mLayoutInflater = LayoutInflater.from(context);
87         mMenu = menu;
88         Resources res = context.getResources();
89         mPaddingSeparator = res.getDimensionPixelOffset(
90                 R.dimen.design_navigation_separator_vertical_padding);
91     }
92 
93     @Override
getMenuView(ViewGroup root)94     public MenuView getMenuView(ViewGroup root) {
95         if (mMenuView == null) {
96             mMenuView = (NavigationMenuView) mLayoutInflater.inflate(
97                     R.layout.design_navigation_menu, root, false);
98             if (mAdapter == null) {
99                 mAdapter = new NavigationMenuAdapter();
100             }
101             mHeaderLayout = (LinearLayout) mLayoutInflater
102                     .inflate(R.layout.design_navigation_item_header,
103                             mMenuView, false);
104             mMenuView.setAdapter(mAdapter);
105         }
106         return mMenuView;
107     }
108 
109     @Override
updateMenuView(boolean cleared)110     public void updateMenuView(boolean cleared) {
111         if (mAdapter != null) {
112             mAdapter.update();
113         }
114     }
115 
116     @Override
setCallback(Callback cb)117     public void setCallback(Callback cb) {
118         mCallback = cb;
119     }
120 
121     @Override
onSubMenuSelected(SubMenuBuilder subMenu)122     public boolean onSubMenuSelected(SubMenuBuilder subMenu) {
123         return false;
124     }
125 
126     @Override
onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing)127     public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
128         if (mCallback != null) {
129             mCallback.onCloseMenu(menu, allMenusAreClosing);
130         }
131     }
132 
133     @Override
flagActionItems()134     public boolean flagActionItems() {
135         return false;
136     }
137 
138     @Override
expandItemActionView(MenuBuilder menu, MenuItemImpl item)139     public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) {
140         return false;
141     }
142 
143     @Override
collapseItemActionView(MenuBuilder menu, MenuItemImpl item)144     public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) {
145         return false;
146     }
147 
148     @Override
getId()149     public int getId() {
150         return mId;
151     }
152 
setId(int id)153     public void setId(int id) {
154         mId = id;
155     }
156 
157     @Override
onSaveInstanceState()158     public Parcelable onSaveInstanceState() {
159         if (Build.VERSION.SDK_INT >= 11) {
160             // API 9-10 does not support ClassLoaderCreator, therefore things can crash if they're
161             // loaded via different loaders. Rather than crash we just won't save state on those
162             // platforms
163             final Bundle state = new Bundle();
164             if (mMenuView != null) {
165                 SparseArray<Parcelable> hierarchy = new SparseArray<>();
166                 mMenuView.saveHierarchyState(hierarchy);
167                 state.putSparseParcelableArray(STATE_HIERARCHY, hierarchy);
168             }
169             if (mAdapter != null) {
170                 state.putBundle(STATE_ADAPTER, mAdapter.createInstanceState());
171             }
172             return state;
173         }
174         return null;
175     }
176 
177     @Override
onRestoreInstanceState(final Parcelable parcelable)178     public void onRestoreInstanceState(final Parcelable parcelable) {
179         if (parcelable instanceof Bundle) {
180             Bundle state = (Bundle) parcelable;
181             SparseArray<Parcelable> hierarchy = state.getSparseParcelableArray(STATE_HIERARCHY);
182             if (hierarchy != null) {
183                 mMenuView.restoreHierarchyState(hierarchy);
184             }
185             Bundle adapterState = state.getBundle(STATE_ADAPTER);
186             if (adapterState != null) {
187                 mAdapter.restoreInstanceState(adapterState);
188             }
189         }
190     }
191 
setCheckedItem(MenuItemImpl item)192     public void setCheckedItem(MenuItemImpl item) {
193         mAdapter.setCheckedItem(item);
194     }
195 
inflateHeaderView(@ayoutRes int res)196     public View inflateHeaderView(@LayoutRes int res) {
197         View view = mLayoutInflater.inflate(res, mHeaderLayout, false);
198         addHeaderView(view);
199         return view;
200     }
201 
addHeaderView(@onNull View view)202     public void addHeaderView(@NonNull View view) {
203         mHeaderLayout.addView(view);
204         // The padding on top should be cleared.
205         mMenuView.setPadding(0, 0, 0, mMenuView.getPaddingBottom());
206     }
207 
removeHeaderView(@onNull View view)208     public void removeHeaderView(@NonNull View view) {
209         mHeaderLayout.removeView(view);
210         if (mHeaderLayout.getChildCount() == 0) {
211             mMenuView.setPadding(0, mPaddingTopDefault, 0, mMenuView.getPaddingBottom());
212         }
213     }
214 
getHeaderCount()215     public int getHeaderCount() {
216         return mHeaderLayout.getChildCount();
217     }
218 
getHeaderView(int index)219     public View getHeaderView(int index) {
220         return mHeaderLayout.getChildAt(index);
221     }
222 
223     @Nullable
getItemTintList()224     public ColorStateList getItemTintList() {
225         return mIconTintList;
226     }
227 
setItemIconTintList(@ullable ColorStateList tint)228     public void setItemIconTintList(@Nullable ColorStateList tint) {
229         mIconTintList = tint;
230         updateMenuView(false);
231     }
232 
233     @Nullable
getItemTextColor()234     public ColorStateList getItemTextColor() {
235         return mTextColor;
236     }
237 
setItemTextColor(@ullable ColorStateList textColor)238     public void setItemTextColor(@Nullable ColorStateList textColor) {
239         mTextColor = textColor;
240         updateMenuView(false);
241     }
242 
setItemTextAppearance(@tyleRes int resId)243     public void setItemTextAppearance(@StyleRes int resId) {
244         mTextAppearance = resId;
245         mTextAppearanceSet = true;
246         updateMenuView(false);
247     }
248 
249     @Nullable
getItemBackground()250     public Drawable getItemBackground() {
251         return mItemBackground;
252     }
253 
setItemBackground(@ullable Drawable itemBackground)254     public void setItemBackground(@Nullable Drawable itemBackground) {
255         mItemBackground = itemBackground;
256         updateMenuView(false);
257     }
258 
setUpdateSuspended(boolean updateSuspended)259     public void setUpdateSuspended(boolean updateSuspended) {
260         if (mAdapter != null) {
261             mAdapter.setUpdateSuspended(updateSuspended);
262         }
263     }
264 
dispatchApplyWindowInsets(WindowInsetsCompat insets)265     public void dispatchApplyWindowInsets(WindowInsetsCompat insets) {
266         int top = insets.getSystemWindowInsetTop();
267         if (mPaddingTopDefault != top) {
268             mPaddingTopDefault = top;
269             if (mHeaderLayout.getChildCount() == 0) {
270                 mMenuView.setPadding(0, mPaddingTopDefault, 0, mMenuView.getPaddingBottom());
271             }
272         }
273         ViewCompat.dispatchApplyWindowInsets(mHeaderLayout, insets);
274     }
275 
276     private abstract static class ViewHolder extends RecyclerView.ViewHolder {
277 
ViewHolder(View itemView)278         public ViewHolder(View itemView) {
279             super(itemView);
280         }
281 
282     }
283 
284     private static class NormalViewHolder extends ViewHolder {
285 
NormalViewHolder(LayoutInflater inflater, ViewGroup parent, View.OnClickListener listener)286         public NormalViewHolder(LayoutInflater inflater, ViewGroup parent,
287                 View.OnClickListener listener) {
288             super(inflater.inflate(R.layout.design_navigation_item, parent, false));
289             itemView.setOnClickListener(listener);
290         }
291 
292     }
293 
294     private static class SubheaderViewHolder extends ViewHolder {
295 
SubheaderViewHolder(LayoutInflater inflater, ViewGroup parent)296         public SubheaderViewHolder(LayoutInflater inflater, ViewGroup parent) {
297             super(inflater.inflate(R.layout.design_navigation_item_subheader, parent, false));
298         }
299 
300     }
301 
302     private static class SeparatorViewHolder extends ViewHolder {
303 
SeparatorViewHolder(LayoutInflater inflater, ViewGroup parent)304         public SeparatorViewHolder(LayoutInflater inflater, ViewGroup parent) {
305             super(inflater.inflate(R.layout.design_navigation_item_separator, parent, false));
306         }
307 
308     }
309 
310     private static class HeaderViewHolder extends ViewHolder {
311 
HeaderViewHolder(View itemView)312         public HeaderViewHolder(View itemView) {
313             super(itemView);
314         }
315 
316     }
317 
318     /**
319      * Handles click events for the menu items. The items has to be {@link NavigationMenuItemView}.
320      */
321     private final View.OnClickListener mOnClickListener = new View.OnClickListener() {
322 
323         @Override
324         public void onClick(View v) {
325             NavigationMenuItemView itemView = (NavigationMenuItemView) v;
326             setUpdateSuspended(true);
327             MenuItemImpl item = itemView.getItemData();
328             boolean result = mMenu.performItemAction(item, NavigationMenuPresenter.this, 0);
329             if (item != null && item.isCheckable() && result) {
330                 mAdapter.setCheckedItem(item);
331             }
332             setUpdateSuspended(false);
333             updateMenuView(false);
334         }
335 
336     };
337 
338     private class NavigationMenuAdapter extends RecyclerView.Adapter<ViewHolder> {
339 
340         private static final String STATE_CHECKED_ITEM = "android:menu:checked";
341 
342         private static final String STATE_ACTION_VIEWS = "android:menu:action_views";
343         private static final int VIEW_TYPE_NORMAL = 0;
344         private static final int VIEW_TYPE_SUBHEADER = 1;
345         private static final int VIEW_TYPE_SEPARATOR = 2;
346         private static final int VIEW_TYPE_HEADER = 3;
347 
348         private final ArrayList<NavigationMenuItem> mItems = new ArrayList<>();
349         private MenuItemImpl mCheckedItem;
350         private boolean mUpdateSuspended;
351 
NavigationMenuAdapter()352         NavigationMenuAdapter() {
353             prepareMenuItems();
354         }
355 
356         @Override
getItemId(int position)357         public long getItemId(int position) {
358             return position;
359         }
360 
361         @Override
getItemCount()362         public int getItemCount() {
363             return mItems.size();
364         }
365 
366         @Override
getItemViewType(int position)367         public int getItemViewType(int position) {
368             NavigationMenuItem item = mItems.get(position);
369             if (item instanceof NavigationMenuSeparatorItem) {
370                 return VIEW_TYPE_SEPARATOR;
371             } else if (item instanceof NavigationMenuHeaderItem) {
372                 return VIEW_TYPE_HEADER;
373             } else if (item instanceof NavigationMenuTextItem) {
374                 NavigationMenuTextItem textItem = (NavigationMenuTextItem) item;
375                 if (textItem.getMenuItem().hasSubMenu()) {
376                     return VIEW_TYPE_SUBHEADER;
377                 } else {
378                     return VIEW_TYPE_NORMAL;
379                 }
380             }
381             throw new RuntimeException("Unknown item type.");
382         }
383 
384         @Override
onCreateViewHolder(ViewGroup parent, int viewType)385         public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
386             switch (viewType) {
387                 case VIEW_TYPE_NORMAL:
388                     return new NormalViewHolder(mLayoutInflater, parent, mOnClickListener);
389                 case VIEW_TYPE_SUBHEADER:
390                     return new SubheaderViewHolder(mLayoutInflater, parent);
391                 case VIEW_TYPE_SEPARATOR:
392                     return new SeparatorViewHolder(mLayoutInflater, parent);
393                 case VIEW_TYPE_HEADER:
394                     return new HeaderViewHolder(mHeaderLayout);
395             }
396             return null;
397         }
398 
399         @Override
onBindViewHolder(ViewHolder holder, int position)400         public void onBindViewHolder(ViewHolder holder, int position) {
401             switch (getItemViewType(position)) {
402                 case VIEW_TYPE_NORMAL: {
403                     NavigationMenuItemView itemView = (NavigationMenuItemView) holder.itemView;
404                     itemView.setIconTintList(mIconTintList);
405                     if (mTextAppearanceSet) {
406                         itemView.setTextAppearance(itemView.getContext(), mTextAppearance);
407                     }
408                     if (mTextColor != null) {
409                         itemView.setTextColor(mTextColor);
410                     }
411                     itemView.setBackgroundDrawable(mItemBackground != null ?
412                             mItemBackground.getConstantState().newDrawable() : null);
413                     NavigationMenuTextItem item = (NavigationMenuTextItem) mItems.get(position);
414                     itemView.setNeedsEmptyIcon(item.needsEmptyIcon);
415                     itemView.initialize(item.getMenuItem(), 0);
416                     break;
417                 }
418                 case VIEW_TYPE_SUBHEADER: {
419                     TextView subHeader = (TextView) holder.itemView;
420                     NavigationMenuTextItem item = (NavigationMenuTextItem) mItems.get(position);
421                     subHeader.setText(item.getMenuItem().getTitle());
422                     break;
423                 }
424                 case VIEW_TYPE_SEPARATOR: {
425                     NavigationMenuSeparatorItem item =
426                             (NavigationMenuSeparatorItem) mItems.get(position);
427                     holder.itemView.setPadding(0, item.getPaddingTop(), 0,
428                             item.getPaddingBottom());
429                     break;
430                 }
431                 case VIEW_TYPE_HEADER: {
432                     break;
433                 }
434             }
435 
436         }
437 
438         @Override
onViewRecycled(ViewHolder holder)439         public void onViewRecycled(ViewHolder holder) {
440             if (holder instanceof NormalViewHolder) {
441                 ((NavigationMenuItemView) holder.itemView).recycle();
442             }
443         }
444 
update()445         public void update() {
446             prepareMenuItems();
447             notifyDataSetChanged();
448         }
449 
450         /**
451          * Flattens the visible menu items of {@link #mMenu} into {@link #mItems},
452          * while inserting separators between items when necessary.
453          */
prepareMenuItems()454         private void prepareMenuItems() {
455             if (mUpdateSuspended) {
456                 return;
457             }
458             mUpdateSuspended = true;
459             mItems.clear();
460             mItems.add(new NavigationMenuHeaderItem());
461 
462             int currentGroupId = -1;
463             int currentGroupStart = 0;
464             boolean currentGroupHasIcon = false;
465             for (int i = 0, totalSize = mMenu.getVisibleItems().size(); i < totalSize; i++) {
466                 MenuItemImpl item = mMenu.getVisibleItems().get(i);
467                 if (item.isChecked()) {
468                     setCheckedItem(item);
469                 }
470                 if (item.isCheckable()) {
471                     item.setExclusiveCheckable(false);
472                 }
473                 if (item.hasSubMenu()) {
474                     SubMenu subMenu = item.getSubMenu();
475                     if (subMenu.hasVisibleItems()) {
476                         if (i != 0) {
477                             mItems.add(new NavigationMenuSeparatorItem(mPaddingSeparator, 0));
478                         }
479                         mItems.add(new NavigationMenuTextItem(item));
480                         boolean subMenuHasIcon = false;
481                         int subMenuStart = mItems.size();
482                         for (int j = 0, size = subMenu.size(); j < size; j++) {
483                             MenuItemImpl subMenuItem = (MenuItemImpl) subMenu.getItem(j);
484                             if (subMenuItem.isVisible()) {
485                                 if (!subMenuHasIcon && subMenuItem.getIcon() != null) {
486                                     subMenuHasIcon = true;
487                                 }
488                                 if (subMenuItem.isCheckable()) {
489                                     subMenuItem.setExclusiveCheckable(false);
490                                 }
491                                 if (item.isChecked()) {
492                                     setCheckedItem(item);
493                                 }
494                                 mItems.add(new NavigationMenuTextItem(subMenuItem));
495                             }
496                         }
497                         if (subMenuHasIcon) {
498                             appendTransparentIconIfMissing(subMenuStart, mItems.size());
499                         }
500                     }
501                 } else {
502                     int groupId = item.getGroupId();
503                     if (groupId != currentGroupId) { // first item in group
504                         currentGroupStart = mItems.size();
505                         currentGroupHasIcon = item.getIcon() != null;
506                         if (i != 0) {
507                             currentGroupStart++;
508                             mItems.add(new NavigationMenuSeparatorItem(
509                                     mPaddingSeparator, mPaddingSeparator));
510                         }
511                     } else if (!currentGroupHasIcon && item.getIcon() != null) {
512                         currentGroupHasIcon = true;
513                         appendTransparentIconIfMissing(currentGroupStart, mItems.size());
514                     }
515                     NavigationMenuTextItem textItem = new NavigationMenuTextItem(item);
516                     textItem.needsEmptyIcon = currentGroupHasIcon;
517                     mItems.add(textItem);
518                     currentGroupId = groupId;
519                 }
520             }
521             mUpdateSuspended = false;
522         }
523 
appendTransparentIconIfMissing(int startIndex, int endIndex)524         private void appendTransparentIconIfMissing(int startIndex, int endIndex) {
525             for (int i = startIndex; i < endIndex; i++) {
526                 NavigationMenuTextItem textItem = (NavigationMenuTextItem) mItems.get(i);
527                 textItem.needsEmptyIcon = true;
528             }
529         }
530 
setCheckedItem(MenuItemImpl checkedItem)531         public void setCheckedItem(MenuItemImpl checkedItem) {
532             if (mCheckedItem == checkedItem || !checkedItem.isCheckable()) {
533                 return;
534             }
535             if (mCheckedItem != null) {
536                 mCheckedItem.setChecked(false);
537             }
538             mCheckedItem = checkedItem;
539             checkedItem.setChecked(true);
540         }
541 
createInstanceState()542         public Bundle createInstanceState() {
543             Bundle state = new Bundle();
544             if (mCheckedItem != null) {
545                 state.putInt(STATE_CHECKED_ITEM, mCheckedItem.getItemId());
546             }
547             // Store the states of the action views.
548             SparseArray<ParcelableSparseArray> actionViewStates = new SparseArray<>();
549             for (NavigationMenuItem navigationMenuItem : mItems) {
550                 if (navigationMenuItem instanceof NavigationMenuTextItem) {
551                     MenuItemImpl item = ((NavigationMenuTextItem) navigationMenuItem).getMenuItem();
552                     View actionView = item != null ? item.getActionView() : null;
553                     if (actionView != null) {
554                         ParcelableSparseArray container = new ParcelableSparseArray();
555                         actionView.saveHierarchyState(container);
556                         actionViewStates.put(item.getItemId(), container);
557                     }
558                 }
559             }
560             state.putSparseParcelableArray(STATE_ACTION_VIEWS, actionViewStates);
561             return state;
562         }
563 
restoreInstanceState(Bundle state)564         public void restoreInstanceState(Bundle state) {
565             int checkedItem = state.getInt(STATE_CHECKED_ITEM, 0);
566             if (checkedItem != 0) {
567                 mUpdateSuspended = true;
568                 for (NavigationMenuItem item : mItems) {
569                     if (item instanceof NavigationMenuTextItem) {
570                         MenuItemImpl menuItem = ((NavigationMenuTextItem) item).getMenuItem();
571                         if (menuItem != null && menuItem.getItemId() == checkedItem) {
572                             setCheckedItem(menuItem);
573                             break;
574                         }
575                     }
576                 }
577                 mUpdateSuspended = false;
578                 prepareMenuItems();
579             }
580             // Restore the states of the action views.
581             SparseArray<ParcelableSparseArray> actionViewStates = state
582                     .getSparseParcelableArray(STATE_ACTION_VIEWS);
583             for (NavigationMenuItem navigationMenuItem : mItems) {
584                 if (navigationMenuItem instanceof NavigationMenuTextItem) {
585                     MenuItemImpl item = ((NavigationMenuTextItem) navigationMenuItem).getMenuItem();
586                     View actionView = item != null ? item.getActionView() : null;
587                     if (actionView != null) {
588                         actionView.restoreHierarchyState(actionViewStates.get(item.getItemId()));
589                     }
590                 }
591             }
592         }
593 
setUpdateSuspended(boolean updateSuspended)594         public void setUpdateSuspended(boolean updateSuspended) {
595             mUpdateSuspended = updateSuspended;
596         }
597 
598     }
599 
600     /**
601      * Unified data model for all sorts of navigation menu items.
602      */
603     private interface NavigationMenuItem {
604     }
605 
606     /**
607      * Normal or subheader items.
608      */
609     private static class NavigationMenuTextItem implements NavigationMenuItem {
610 
611         private final MenuItemImpl mMenuItem;
612 
613         boolean needsEmptyIcon;
614 
NavigationMenuTextItem(MenuItemImpl item)615         private NavigationMenuTextItem(MenuItemImpl item) {
616             mMenuItem = item;
617         }
618 
getMenuItem()619         public MenuItemImpl getMenuItem() {
620             return mMenuItem;
621         }
622 
623     }
624 
625     /**
626      * Separator items.
627      */
628     private static class NavigationMenuSeparatorItem implements NavigationMenuItem {
629 
630         private final int mPaddingTop;
631 
632         private final int mPaddingBottom;
633 
NavigationMenuSeparatorItem(int paddingTop, int paddingBottom)634         public NavigationMenuSeparatorItem(int paddingTop, int paddingBottom) {
635             mPaddingTop = paddingTop;
636             mPaddingBottom = paddingBottom;
637         }
638 
getPaddingTop()639         public int getPaddingTop() {
640             return mPaddingTop;
641         }
642 
getPaddingBottom()643         public int getPaddingBottom() {
644             return mPaddingBottom;
645         }
646 
647     }
648 
649     /**
650      * Header (not subheader) items.
651      */
652     private static class NavigationMenuHeaderItem implements NavigationMenuItem {
653         // The actual content is hold by NavigationMenuPresenter#mHeaderLayout.
654     }
655 
656 }
657