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