NavigationMenuPresenter.java revision a5081dfb26b3664d97d5fe09b9b6a9c9667e0e9f
131a49efe2adb59e31611f6871895a3243d835127Yuichi Araki/*
231a49efe2adb59e31611f6871895a3243d835127Yuichi Araki * Copyright (C) 2015 The Android Open Source Project
331a49efe2adb59e31611f6871895a3243d835127Yuichi Araki *
431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki * Licensed under the Apache License, Version 2.0 (the "License");
531a49efe2adb59e31611f6871895a3243d835127Yuichi Araki * you may not use this file except in compliance with the License.
631a49efe2adb59e31611f6871895a3243d835127Yuichi Araki * You may obtain a copy of the License at
731a49efe2adb59e31611f6871895a3243d835127Yuichi Araki *
831a49efe2adb59e31611f6871895a3243d835127Yuichi Araki *      http://www.apache.org/licenses/LICENSE-2.0
931a49efe2adb59e31611f6871895a3243d835127Yuichi Araki *
1031a49efe2adb59e31611f6871895a3243d835127Yuichi Araki * Unless required by applicable law or agreed to in writing, software
1131a49efe2adb59e31611f6871895a3243d835127Yuichi Araki * distributed under the License is distributed on an "AS IS" BASIS,
1231a49efe2adb59e31611f6871895a3243d835127Yuichi Araki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1331a49efe2adb59e31611f6871895a3243d835127Yuichi Araki * See the License for the specific language governing permissions and
1431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki * limitations under the License.
1531a49efe2adb59e31611f6871895a3243d835127Yuichi Araki */
1631a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
1731a49efe2adb59e31611f6871895a3243d835127Yuichi Arakipackage android.support.design.internal;
1831a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
1931a49efe2adb59e31611f6871895a3243d835127Yuichi Arakiimport android.content.Context;
20d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Arakiimport android.content.res.ColorStateList;
2101090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Arakiimport android.os.Bundle;
2231a49efe2adb59e31611f6871895a3243d835127Yuichi Arakiimport android.os.Parcelable;
23d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Arakiimport android.support.annotation.DrawableRes;
2401090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Arakiimport android.support.annotation.LayoutRes;
2501090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Arakiimport android.support.annotation.NonNull;
26d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Arakiimport android.support.annotation.Nullable;
2731a49efe2adb59e31611f6871895a3243d835127Yuichi Arakiimport android.support.design.R;
2831a49efe2adb59e31611f6871895a3243d835127Yuichi Arakiimport android.support.v7.internal.view.menu.MenuBuilder;
2931a49efe2adb59e31611f6871895a3243d835127Yuichi Arakiimport android.support.v7.internal.view.menu.MenuItemImpl;
3031a49efe2adb59e31611f6871895a3243d835127Yuichi Arakiimport android.support.v7.internal.view.menu.MenuPresenter;
3131a49efe2adb59e31611f6871895a3243d835127Yuichi Arakiimport android.support.v7.internal.view.menu.MenuView;
3231a49efe2adb59e31611f6871895a3243d835127Yuichi Arakiimport android.support.v7.internal.view.menu.SubMenuBuilder;
3301090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Arakiimport android.util.SparseArray;
3431a49efe2adb59e31611f6871895a3243d835127Yuichi Arakiimport android.view.LayoutInflater;
3501090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Arakiimport android.view.MenuItem;
3601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Arakiimport android.view.SubMenu;
3731a49efe2adb59e31611f6871895a3243d835127Yuichi Arakiimport android.view.View;
3831a49efe2adb59e31611f6871895a3243d835127Yuichi Arakiimport android.view.ViewGroup;
3931a49efe2adb59e31611f6871895a3243d835127Yuichi Arakiimport android.widget.AdapterView;
4031a49efe2adb59e31611f6871895a3243d835127Yuichi Arakiimport android.widget.BaseAdapter;
4101090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Arakiimport android.widget.TextView;
4201090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
4301090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Arakiimport java.util.ArrayList;
4431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
4531a49efe2adb59e31611f6871895a3243d835127Yuichi Araki/**
4631a49efe2adb59e31611f6871895a3243d835127Yuichi Araki * @hide
4731a49efe2adb59e31611f6871895a3243d835127Yuichi Araki */
4831a49efe2adb59e31611f6871895a3243d835127Yuichi Arakipublic class NavigationMenuPresenter implements MenuPresenter, AdapterView.OnItemClickListener {
4931a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
5001090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    private static final String STATE_HIERARCHY = "android:menu:list";
5101090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
5231a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    private NavigationMenuView mMenuView;
5331a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
5431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    private Callback mCallback;
5531a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
5631a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    private MenuBuilder mMenu;
5731a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
5801090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    private ArrayList<NavigationMenuItem> mItems = new ArrayList<>();
5901090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
6031a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    private int mId;
6131a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
6231a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    private NavigationMenuAdapter mAdapter;
6331a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
6431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    private LayoutInflater mLayoutInflater;
6531a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
6601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    private View mSpace;
6701090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
68d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki    private ColorStateList mItemTintList;
69d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki
70d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki    private int mItemBackgroundResource;
71d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki
7201090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    /**
7301090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki     * Padding to be inserted at the top of the list to avoid the first menu item
7401090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki     * from being placed underneath the status bar.
7501090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki     */
7601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    private int mPaddingTopDefault;
7701090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
7831a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    @Override
7931a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    public void initForMenu(Context context, MenuBuilder menu) {
8031a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        mLayoutInflater = LayoutInflater.from(context);
8131a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        mMenu = menu;
8201090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        mPaddingTopDefault = context.getResources().getDimensionPixelOffset(
83a5081dfb26b3664d97d5fe09b9b6a9c9667e0e9fYuichi Araki                R.dimen.navigation_padding_top_default);
8431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
8531a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
8631a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    @Override
8731a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    public MenuView getMenuView(ViewGroup root) {
8831a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        if (mMenuView == null) {
8931a49efe2adb59e31611f6871895a3243d835127Yuichi Araki            mMenuView = (NavigationMenuView) mLayoutInflater.inflate(
90a5081dfb26b3664d97d5fe09b9b6a9c9667e0e9fYuichi Araki                    R.layout.design_navigation_menu, root, false);
9131a49efe2adb59e31611f6871895a3243d835127Yuichi Araki            if (mAdapter == null) {
9231a49efe2adb59e31611f6871895a3243d835127Yuichi Araki                mAdapter = new NavigationMenuAdapter();
9331a49efe2adb59e31611f6871895a3243d835127Yuichi Araki            }
9431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki            mMenuView.setAdapter(mAdapter);
9531a49efe2adb59e31611f6871895a3243d835127Yuichi Araki            mMenuView.setOnItemClickListener(this);
9631a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        }
9731a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        return mMenuView;
9831a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
9931a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
10031a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    @Override
10131a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    public void updateMenuView(boolean cleared) {
10231a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        if (mAdapter != null) {
10301090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            prepareMenuItems();
10431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki            mAdapter.notifyDataSetChanged();
10531a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        }
10631a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
10731a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
10801090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    /**
10901090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki     * Flattens the visible menu items of {@link #mMenu} into {@link #mItems},
11001090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki     * while inserting separators between items when necessary.
11101090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki     */
11201090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    private void prepareMenuItems() {
11301090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        mItems.clear();
11401090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        int currentGroupId = 0;
115d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki        for (int i = 0, totalSize = mMenu.getVisibleItems().size(); i < totalSize; i++) {
116d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki            MenuItemImpl item = mMenu.getVisibleItems().get(i);
11701090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            if (item.hasSubMenu()) {
11801090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                SubMenu subMenu = item.getSubMenu();
11901090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                if (subMenu.hasVisibleItems()) {
120d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki                    if (i != 0) {
121d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki                        mItems.add(NavigationMenuItem.SEPARATOR);
122d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki                    }
12301090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                    mItems.add(NavigationMenuItem.of(item));
124d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki                    for (int j = 0, size = subMenu.size(); j < size; j++) {
125d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki                        MenuItem subMenuItem = subMenu.getItem(j);
12601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                        if (subMenuItem.isVisible()) {
12701090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                            mItems.add(NavigationMenuItem.of((MenuItemImpl) subMenuItem));
12801090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                        }
12901090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                    }
13001090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                }
13101090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            } else {
13201090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                int groupId = item.getGroupId();
133d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki                if (groupId != currentGroupId && i != 0) {
13401090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                    mItems.add(NavigationMenuItem.SEPARATOR);
13501090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                }
13601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                mItems.add(NavigationMenuItem.of(item));
13701090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                currentGroupId = groupId;
13801090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            }
13901090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        }
14001090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    }
14101090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
14231a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    @Override
14331a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    public void setCallback(Callback cb) {
14431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        mCallback = cb;
14531a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
14631a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
14731a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    @Override
14831a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    public boolean onSubMenuSelected(SubMenuBuilder subMenu) {
14931a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        return false;
15031a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
15131a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
15231a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    @Override
15331a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
15431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        if (mCallback != null) {
15531a49efe2adb59e31611f6871895a3243d835127Yuichi Araki            mCallback.onCloseMenu(menu, allMenusAreClosing);
15631a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        }
15731a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
15831a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
15931a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    @Override
16031a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    public boolean flagActionItems() {
16131a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        return false;
16231a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
16331a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
16431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    @Override
16531a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) {
16631a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        return false;
16731a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
16831a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
16931a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    @Override
17031a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) {
17131a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        return false;
17231a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
17331a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
17431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    @Override
17531a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    public int getId() {
17631a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        return mId;
17731a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
17831a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
17931a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    public void setId(int id) {
18031a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        mId = id;
18131a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
18231a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
18331a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    @Override
18431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    public Parcelable onSaveInstanceState() {
18501090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        Bundle state = new Bundle();
18601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        SparseArray<Parcelable> hierarchy = new SparseArray<>();
18701090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        if (mMenuView != null) {
18801090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            mMenuView.saveHierarchyState(hierarchy);
18901090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        }
19001090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        state.putSparseParcelableArray(STATE_HIERARCHY, hierarchy);
19101090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        return state;
19231a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
19331a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
19431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    @Override
19501090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    public void onRestoreInstanceState(Parcelable parcelable) {
19601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        Bundle state = (Bundle) parcelable;
19701090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        SparseArray<Parcelable> hierarchy = state.getSparseParcelableArray(STATE_HIERARCHY);
19801090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        if (hierarchy != null) {
19901090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            mMenuView.restoreHierarchyState(hierarchy);
20001090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        }
20131a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
20231a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
20331a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    @Override
20431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
20501090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        int positionInAdapter = position - mMenuView.getHeaderViewsCount();
20601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        if (positionInAdapter >= 0) {
20701090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            mMenu.performItemAction(mAdapter.getItem(positionInAdapter).getMenuItem(), this, 0);
20801090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        }
20901090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    }
21001090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
21101090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    public View inflateHeaderView(@LayoutRes int res) {
21201090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        View view = mLayoutInflater.inflate(res, mMenuView, false);
21301090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        addHeaderView(view);
21401090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        onHeaderAdded();
21501090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        return view;
21601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    }
21701090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
21801090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    public void addHeaderView(@NonNull View view) {
21901090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        mMenuView.addHeaderView(view);
22001090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        onHeaderAdded();
22101090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    }
22201090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
22301090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    private void onHeaderAdded() {
22401090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        // If we have just added the first header, we also need to insert a space
22501090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        // between the header and the menu items.
22601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        if (mMenuView.getHeaderViewsCount() == 1) {
227a5081dfb26b3664d97d5fe09b9b6a9c9667e0e9fYuichi Araki            mSpace = mLayoutInflater.inflate(R.layout.design_navigation_item_space, mMenuView,
228a5081dfb26b3664d97d5fe09b9b6a9c9667e0e9fYuichi Araki                    false);
22901090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            mMenuView.addHeaderView(mSpace);
23001090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        }
23101090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        // The padding on top should be cleared.
23201090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        mMenuView.setPadding(0, 0, 0, 0);
23301090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    }
23401090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
23501090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    public void removeHeaderView(@NonNull View view) {
23601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        if (mMenuView.removeHeaderView(view)) {
23701090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            // Remove the space if it is the only remained header
23801090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            if (mMenuView.getHeaderViewsCount() == 1) {
23901090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                mMenuView.removeHeaderView(mSpace);
24001090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                mMenuView.setPadding(0, mPaddingTopDefault, 0, 0);
24101090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            }
24201090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        }
24331a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
24431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
245d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki    @Nullable
246d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki    public ColorStateList getItemTintList() {
247d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki        return mItemTintList;
248d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki    }
249d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki
250d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki    public void setItemTintList(@Nullable ColorStateList itemTintList) {
251d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki        mItemTintList = itemTintList;
252d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki    }
253d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki
254d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki    @DrawableRes
255d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki    public int getItemBackgroundResource() {
256d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki        return mItemBackgroundResource;
257d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki    }
258d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki
259d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki    public void setItemBackgroundResource(@DrawableRes int itemBackgroundResource) {
260d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki        mItemBackgroundResource = itemBackgroundResource;
261d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki    }
262d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki
26331a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    private class NavigationMenuAdapter extends BaseAdapter {
26431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
26501090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        private static final int VIEW_TYPE_NORMAL = 0;
26601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
26701090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        private static final int VIEW_TYPE_SUBHEADER = 1;
26801090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
26901090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        private static final int VIEW_TYPE_SEPARATOR = 2;
27001090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
27131a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        @Override
27231a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        public int getCount() {
27301090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            return mItems.size();
27431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        }
27531a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
27631a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        @Override
27701090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        public NavigationMenuItem getItem(int position) {
27801090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            return mItems.get(position);
27931a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        }
28031a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
28131a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        @Override
28231a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        public long getItemId(int position) {
28331a49efe2adb59e31611f6871895a3243d835127Yuichi Araki            return position;
28431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        }
28531a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
28631a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        @Override
28701090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        public int getViewTypeCount() {
28801090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            return 3;
28901090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        }
29001090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
29101090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        @Override
29201090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        public int getItemViewType(int position) {
29301090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            NavigationMenuItem item = getItem(position);
29401090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            if (item.isSeparator()) {
29501090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                return VIEW_TYPE_SEPARATOR;
29601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            } else if (item.getMenuItem().hasSubMenu()) {
29701090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                return VIEW_TYPE_SUBHEADER;
29801090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            } else {
29901090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                return VIEW_TYPE_NORMAL;
30001090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            }
30101090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        }
30201090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
30301090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        @Override
30431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        public View getView(int position, View convertView, ViewGroup parent) {
30501090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            NavigationMenuItem item = getItem(position);
30601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            int viewType = getItemViewType(position);
30701090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            switch (viewType) {
30801090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                case VIEW_TYPE_NORMAL:
30901090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                    if (convertView == null) {
310a5081dfb26b3664d97d5fe09b9b6a9c9667e0e9fYuichi Araki                        convertView = mLayoutInflater.inflate(R.layout.design_navigation_item,
311a5081dfb26b3664d97d5fe09b9b6a9c9667e0e9fYuichi Araki                                parent, false);
31201090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                    }
313d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki                    NavigationMenuItemView itemView = (NavigationMenuItemView) convertView;
314d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki                    itemView.setTintList(mItemTintList);
315d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki                    itemView.setBackgroundResource(mItemBackgroundResource);
31601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                    itemView.initialize(item.getMenuItem(), 0);
31701090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                    break;
31801090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                case VIEW_TYPE_SUBHEADER:
31901090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                    if (convertView == null) {
320a5081dfb26b3664d97d5fe09b9b6a9c9667e0e9fYuichi Araki                        convertView = mLayoutInflater.inflate(
321a5081dfb26b3664d97d5fe09b9b6a9c9667e0e9fYuichi Araki                                R.layout.design_navigation_item_subheader, parent, false);
32201090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                    }
32301090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                    TextView subHeader = (TextView) convertView;
32401090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                    subHeader.setText(item.getMenuItem().getTitle());
32501090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                    break;
32601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                case VIEW_TYPE_SEPARATOR:
32701090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                    if (convertView == null) {
328a5081dfb26b3664d97d5fe09b9b6a9c9667e0e9fYuichi Araki                        convertView = mLayoutInflater.inflate(
329a5081dfb26b3664d97d5fe09b9b6a9c9667e0e9fYuichi Araki                                R.layout.design_navigation_item_separator, parent, false);
33001090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                    }
33101090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                    break;
33231a49efe2adb59e31611f6871895a3243d835127Yuichi Araki            }
33331a49efe2adb59e31611f6871895a3243d835127Yuichi Araki            return convertView;
33431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        }
33501090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
33601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        @Override
33701090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        public boolean areAllItemsEnabled() {
33801090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            return false;
33901090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        }
34001090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
34101090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        @Override
34201090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        public boolean isEnabled(int position) {
34301090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            return getItem(position).isEnabled();
34401090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        }
34501090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
34601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    }
34701090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
34801090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    /**
34901090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki     * Wraps {@link MenuItemImpl}. This allows separators to be counted as items in list.
35001090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki     */
35101090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    private static class NavigationMenuItem {
35201090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
35301090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        private static final NavigationMenuItem SEPARATOR = new NavigationMenuItem(null);
35401090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
35501090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        private final MenuItemImpl mMenuItem;
35601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
35701090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        private NavigationMenuItem(MenuItemImpl item) {
35801090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            mMenuItem = item;
35901090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        }
36001090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
36101090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        public static NavigationMenuItem of(MenuItemImpl item) {
36201090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            return new NavigationMenuItem(item);
36301090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        }
36401090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
36501090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        public boolean isSeparator() {
36601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            return this == SEPARATOR;
36701090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        }
36801090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
36901090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        public MenuItemImpl getMenuItem() {
37001090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            return mMenuItem;
37101090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        }
37201090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
37301090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        public boolean isEnabled() {
37401090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            // Separators and subheaders never respond to click
37501090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            return mMenuItem != null && !mMenuItem.hasSubMenu() && mMenuItem.isEnabled();
37601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        }
37701090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
37831a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
37931a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
38031a49efe2adb59e31611f6871895a3243d835127Yuichi Araki}
381