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