NavigationMenuPresenter.java revision ca2f07c9cc83b98d73a18da7177044ee147ffb94
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;
2160abdeb39630c4c74a4c401e221f0c968caa26f5Yuichi Arakiimport android.content.res.Resources;
228bc6f4dfa590d8cd872a9894804a4c80d01a5d87Yuichi Arakiimport android.graphics.drawable.ColorDrawable;
23a63940ca14cd3ad9620e94f709930bb968525c57Chris Banesimport android.graphics.drawable.Drawable;
2401090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Arakiimport android.os.Bundle;
2531a49efe2adb59e31611f6871895a3243d835127Yuichi Arakiimport android.os.Parcelable;
2601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Arakiimport android.support.annotation.LayoutRes;
2701090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Arakiimport android.support.annotation.NonNull;
28d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Arakiimport android.support.annotation.Nullable;
29153fa9a03422419cd56b7d17def1ae907fc7b5cfChris Banesimport android.support.annotation.StyleRes;
3031a49efe2adb59e31611f6871895a3243d835127Yuichi Arakiimport android.support.design.R;
3131a49efe2adb59e31611f6871895a3243d835127Yuichi Arakiimport android.support.v7.internal.view.menu.MenuBuilder;
3231a49efe2adb59e31611f6871895a3243d835127Yuichi Arakiimport android.support.v7.internal.view.menu.MenuItemImpl;
3331a49efe2adb59e31611f6871895a3243d835127Yuichi Arakiimport android.support.v7.internal.view.menu.MenuPresenter;
3431a49efe2adb59e31611f6871895a3243d835127Yuichi Arakiimport android.support.v7.internal.view.menu.MenuView;
3531a49efe2adb59e31611f6871895a3243d835127Yuichi Arakiimport android.support.v7.internal.view.menu.SubMenuBuilder;
3601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Arakiimport android.util.SparseArray;
3731a49efe2adb59e31611f6871895a3243d835127Yuichi Arakiimport android.view.LayoutInflater;
3801090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Arakiimport android.view.MenuItem;
3901090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Arakiimport android.view.SubMenu;
4031a49efe2adb59e31611f6871895a3243d835127Yuichi Arakiimport android.view.View;
4131a49efe2adb59e31611f6871895a3243d835127Yuichi Arakiimport android.view.ViewGroup;
42ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banesimport android.widget.AdapterView;
43ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banesimport android.widget.BaseAdapter;
4472fa50f289d462aae5038e8dd78e134a0fffcf12Yuichi Arakiimport android.widget.LinearLayout;
4501090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Arakiimport android.widget.TextView;
4601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
4701090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Arakiimport java.util.ArrayList;
4831a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
4931a49efe2adb59e31611f6871895a3243d835127Yuichi Araki/**
5031a49efe2adb59e31611f6871895a3243d835127Yuichi Araki * @hide
5131a49efe2adb59e31611f6871895a3243d835127Yuichi Araki */
52ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banespublic class NavigationMenuPresenter implements MenuPresenter, AdapterView.OnItemClickListener {
5331a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
5401090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    private static final String STATE_HIERARCHY = "android:menu:list";
5576bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki    private static final String STATE_ADAPTER = "android:menu:adapter";
5601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
5731a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    private NavigationMenuView mMenuView;
58ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes    private LinearLayout mHeader;
5931a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
6031a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    private Callback mCallback;
6131a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    private MenuBuilder mMenu;
6231a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    private int mId;
6331a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
6431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    private NavigationMenuAdapter mAdapter;
6531a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    private LayoutInflater mLayoutInflater;
6631a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
67153fa9a03422419cd56b7d17def1ae907fc7b5cfChris Banes    private int mTextAppearance;
68153fa9a03422419cd56b7d17def1ae907fc7b5cfChris Banes    private boolean mTextAppearanceSet;
69a63940ca14cd3ad9620e94f709930bb968525c57Chris Banes    private ColorStateList mTextColor;
70a63940ca14cd3ad9620e94f709930bb968525c57Chris Banes    private ColorStateList mIconTintList;
71a63940ca14cd3ad9620e94f709930bb968525c57Chris Banes    private Drawable mItemBackground;
72d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki
7301090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    /**
7401090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki     * Padding to be inserted at the top of the list to avoid the first menu item
7501090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki     * from being placed underneath the status bar.
7601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki     */
7701090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    private int mPaddingTopDefault;
7801090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
7960abdeb39630c4c74a4c401e221f0c968caa26f5Yuichi Araki    /**
8060abdeb39630c4c74a4c401e221f0c968caa26f5Yuichi Araki     * Padding for separators between items
8160abdeb39630c4c74a4c401e221f0c968caa26f5Yuichi Araki     */
8260abdeb39630c4c74a4c401e221f0c968caa26f5Yuichi Araki    private int mPaddingSeparator;
8360abdeb39630c4c74a4c401e221f0c968caa26f5Yuichi Araki
8431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    @Override
8531a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    public void initForMenu(Context context, MenuBuilder menu) {
8631a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        mLayoutInflater = LayoutInflater.from(context);
8731a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        mMenu = menu;
8860abdeb39630c4c74a4c401e221f0c968caa26f5Yuichi Araki        Resources res = context.getResources();
89a577676a64e5353b8ec927117151aa6be84adf66Chris Banes        mPaddingTopDefault = res.getDimensionPixelOffset(
90a577676a64e5353b8ec927117151aa6be84adf66Chris Banes                R.dimen.design_navigation_padding_top_default);
9160abdeb39630c4c74a4c401e221f0c968caa26f5Yuichi Araki        mPaddingSeparator = res.getDimensionPixelOffset(
92a577676a64e5353b8ec927117151aa6be84adf66Chris Banes                R.dimen.design_navigation_separator_vertical_padding);
9331a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
9431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
9531a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    @Override
9631a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    public MenuView getMenuView(ViewGroup root) {
9731a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        if (mMenuView == null) {
9831a49efe2adb59e31611f6871895a3243d835127Yuichi Araki            mMenuView = (NavigationMenuView) mLayoutInflater.inflate(
99a5081dfb26b3664d97d5fe09b9b6a9c9667e0e9fYuichi Araki                    R.layout.design_navigation_menu, root, false);
10031a49efe2adb59e31611f6871895a3243d835127Yuichi Araki            if (mAdapter == null) {
10131a49efe2adb59e31611f6871895a3243d835127Yuichi Araki                mAdapter = new NavigationMenuAdapter();
10231a49efe2adb59e31611f6871895a3243d835127Yuichi Araki            }
103ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            mHeader = (LinearLayout) mLayoutInflater.inflate(R.layout.design_navigation_item_header,
104ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                    mMenuView, false);
105ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            mMenuView.addHeaderView(mHeader, null, false);
10631a49efe2adb59e31611f6871895a3243d835127Yuichi Araki            mMenuView.setAdapter(mAdapter);
107ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            mMenuView.setOnItemClickListener(this);
10831a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        }
10931a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        return mMenuView;
11031a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
11131a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
11231a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    @Override
11331a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    public void updateMenuView(boolean cleared) {
11431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        if (mAdapter != null) {
115ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            mAdapter.notifyDataSetChanged();
11631a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        }
11731a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
11831a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
11931a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    @Override
12031a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    public void setCallback(Callback cb) {
12131a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        mCallback = cb;
12231a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
12331a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
12431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    @Override
12531a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    public boolean onSubMenuSelected(SubMenuBuilder subMenu) {
12631a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        return false;
12731a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
12831a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
12931a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    @Override
13031a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
13131a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        if (mCallback != null) {
13231a49efe2adb59e31611f6871895a3243d835127Yuichi Araki            mCallback.onCloseMenu(menu, allMenusAreClosing);
13331a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        }
13431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
13531a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
13631a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    @Override
13731a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    public boolean flagActionItems() {
13831a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        return false;
13931a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
14031a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
14131a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    @Override
14231a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) {
14331a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        return false;
14431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
14531a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
14631a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    @Override
14731a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) {
14831a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        return false;
14931a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
15031a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
15131a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    @Override
15231a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    public int getId() {
15331a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        return mId;
15431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
15531a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
15631a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    public void setId(int id) {
15731a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        mId = id;
15831a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
15931a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
16031a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    @Override
16131a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    public Parcelable onSaveInstanceState() {
16201090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        Bundle state = new Bundle();
16301090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        if (mMenuView != null) {
16476bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki            SparseArray<Parcelable> hierarchy = new SparseArray<>();
16501090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            mMenuView.saveHierarchyState(hierarchy);
16676bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki            state.putSparseParcelableArray(STATE_HIERARCHY, hierarchy);
16776bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki        }
16876bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki        if (mAdapter != null) {
16976bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki            state.putBundle(STATE_ADAPTER, mAdapter.createInstanceState());
17001090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        }
17101090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        return state;
17231a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
17331a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
17431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    @Override
17501090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    public void onRestoreInstanceState(Parcelable parcelable) {
17601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        Bundle state = (Bundle) parcelable;
17701090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        SparseArray<Parcelable> hierarchy = state.getSparseParcelableArray(STATE_HIERARCHY);
17801090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        if (hierarchy != null) {
17901090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            mMenuView.restoreHierarchyState(hierarchy);
18001090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        }
18176bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki        Bundle adapterState = state.getBundle(STATE_ADAPTER);
18276bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki        if (adapterState != null) {
18376bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki            mAdapter.restoreInstanceState(adapterState);
18476bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki        }
18531a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
18631a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
187ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes    @Override
188ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
189ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        int positionInAdapter = position - mMenuView.getHeaderViewsCount();
190ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        if (positionInAdapter >= 0) {
191ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            setUpdateSuspended(true);
192ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            MenuItemImpl item = mAdapter.getItem(positionInAdapter).getMenuItem();
193ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            boolean result = mMenu.performItemAction(item, this, 0);
194ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            if (item != null && item.isCheckable() && result) {
195ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                mAdapter.setCheckedItem(item);
196ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            }
197ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            setUpdateSuspended(false);
198ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            updateMenuView(false);
199ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        }
200ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes    }
201ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes
202f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki    public void setCheckedItem(MenuItemImpl item) {
203f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki        mAdapter.setCheckedItem(item);
204f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki    }
205f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki
20601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    public View inflateHeaderView(@LayoutRes int res) {
207ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        View view = mLayoutInflater.inflate(res, mHeader, false);
20801090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        addHeaderView(view);
20901090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        return view;
21001090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    }
21101090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
21201090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    public void addHeaderView(@NonNull View view) {
213ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        mHeader.addView(view);
21401090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        // The padding on top should be cleared.
21560abdeb39630c4c74a4c401e221f0c968caa26f5Yuichi Araki        mMenuView.setPadding(0, 0, 0, mMenuView.getPaddingBottom());
21601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    }
21701090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
21801090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    public void removeHeaderView(@NonNull View view) {
219ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        mHeader.removeView(view);
220ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        if (mHeader.getChildCount() == 0) {
22172fa50f289d462aae5038e8dd78e134a0fffcf12Yuichi Araki            mMenuView.setPadding(0, mPaddingTopDefault, 0, mMenuView.getPaddingBottom());
22201090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        }
22331a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
22431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
225d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki    @Nullable
226d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki    public ColorStateList getItemTintList() {
227a63940ca14cd3ad9620e94f709930bb968525c57Chris Banes        return mIconTintList;
228d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki    }
229d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki
230a63940ca14cd3ad9620e94f709930bb968525c57Chris Banes    public void setItemIconTintList(@Nullable ColorStateList tint) {
231a63940ca14cd3ad9620e94f709930bb968525c57Chris Banes        mIconTintList = tint;
232153fa9a03422419cd56b7d17def1ae907fc7b5cfChris Banes        updateMenuView(false);
233d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki    }
234d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki
235a63940ca14cd3ad9620e94f709930bb968525c57Chris Banes    @Nullable
236a63940ca14cd3ad9620e94f709930bb968525c57Chris Banes    public ColorStateList getItemTextColor() {
237a63940ca14cd3ad9620e94f709930bb968525c57Chris Banes        return mTextColor;
238a63940ca14cd3ad9620e94f709930bb968525c57Chris Banes    }
239a63940ca14cd3ad9620e94f709930bb968525c57Chris Banes
240a63940ca14cd3ad9620e94f709930bb968525c57Chris Banes    public void setItemTextColor(@Nullable ColorStateList textColor) {
241a63940ca14cd3ad9620e94f709930bb968525c57Chris Banes        mTextColor = textColor;
242153fa9a03422419cd56b7d17def1ae907fc7b5cfChris Banes        updateMenuView(false);
243153fa9a03422419cd56b7d17def1ae907fc7b5cfChris Banes    }
244153fa9a03422419cd56b7d17def1ae907fc7b5cfChris Banes
245153fa9a03422419cd56b7d17def1ae907fc7b5cfChris Banes    public void setItemTextAppearance(@StyleRes int resId) {
246153fa9a03422419cd56b7d17def1ae907fc7b5cfChris Banes        mTextAppearance = resId;
247153fa9a03422419cd56b7d17def1ae907fc7b5cfChris Banes        mTextAppearanceSet = true;
248153fa9a03422419cd56b7d17def1ae907fc7b5cfChris Banes        updateMenuView(false);
249a63940ca14cd3ad9620e94f709930bb968525c57Chris Banes    }
250a63940ca14cd3ad9620e94f709930bb968525c57Chris Banes
251a63940ca14cd3ad9620e94f709930bb968525c57Chris Banes    public Drawable getItemBackground() {
252a63940ca14cd3ad9620e94f709930bb968525c57Chris Banes        return mItemBackground;
253d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki    }
254d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki
255a63940ca14cd3ad9620e94f709930bb968525c57Chris Banes    public void setItemBackground(Drawable itemBackground) {
256a63940ca14cd3ad9620e94f709930bb968525c57Chris Banes        mItemBackground = itemBackground;
257d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki    }
258d3ee2c7d22c0cb204ea9077fa9e64511266d6799Yuichi Araki
259cc7a09fc0018e348027151daecf581b1d1b78f11Yuichi Araki    public void setUpdateSuspended(boolean updateSuspended) {
260cc7a09fc0018e348027151daecf581b1d1b78f11Yuichi Araki        if (mAdapter != null) {
261cc7a09fc0018e348027151daecf581b1d1b78f11Yuichi Araki            mAdapter.setUpdateSuspended(updateSuspended);
262cc7a09fc0018e348027151daecf581b1d1b78f11Yuichi Araki        }
263cc7a09fc0018e348027151daecf581b1d1b78f11Yuichi Araki    }
264cc7a09fc0018e348027151daecf581b1d1b78f11Yuichi Araki
265ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes    private class NavigationMenuAdapter extends BaseAdapter {
26676bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki
267f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki        private static final String STATE_CHECKED_ITEM = "android:menu:checked";
26876bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki
26936d347c02fa8da71ccd69634484be8156fa0085bYuichi Araki        private static final String STATE_ACTION_VIEWS = "android:menu:action_views";
27001090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        private static final int VIEW_TYPE_NORMAL = 0;
27101090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        private static final int VIEW_TYPE_SUBHEADER = 1;
27201090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        private static final int VIEW_TYPE_SEPARATOR = 2;
27301090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
2743a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes        private final ArrayList<NavigationMenuItem> mItems = new ArrayList<>();
275f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki        private MenuItemImpl mCheckedItem;
2763a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes        private ColorDrawable mTransparentIcon;
27776bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki        private boolean mUpdateSuspended;
2783a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes
2793a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes        NavigationMenuAdapter() {
2803a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes            prepareMenuItems();
2813a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes        }
2823a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes
28331a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        @Override
284ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        public int getCount() {
285ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            return mItems.size();
286ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        }
287ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes
288ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        @Override
289ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        public NavigationMenuItem getItem(int position) {
290ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            return mItems.get(position);
291ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        }
292ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes
293ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        @Override
29431a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        public long getItemId(int position) {
29531a49efe2adb59e31611f6871895a3243d835127Yuichi Araki            return position;
29631a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        }
29731a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
29831a49efe2adb59e31611f6871895a3243d835127Yuichi Araki        @Override
299ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        public int getViewTypeCount() {
300ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            return 3;
30101090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        }
30201090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
30301090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        @Override
30401090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        public int getItemViewType(int position) {
305ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            NavigationMenuItem item = getItem(position);
306ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            if (item.isSeparator()) {
30701090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                return VIEW_TYPE_SEPARATOR;
308ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            } else if (item.getMenuItem().hasSubMenu()) {
309ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                return VIEW_TYPE_SUBHEADER;
310ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            } else {
311ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                return VIEW_TYPE_NORMAL;
31201090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            }
31301090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        }
31401090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
31501090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        @Override
316ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        public View getView(int position, View convertView, ViewGroup parent) {
317ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            NavigationMenuItem item = getItem(position);
318ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            int viewType = getItemViewType(position);
31901090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki            switch (viewType) {
32001090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                case VIEW_TYPE_NORMAL:
321ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                    if (convertView == null) {
322ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                        convertView = mLayoutInflater.inflate(R.layout.design_navigation_item,
323ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                                parent, false);
324ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                    }
325ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                    NavigationMenuItemView itemView = (NavigationMenuItemView) convertView;
326a63940ca14cd3ad9620e94f709930bb968525c57Chris Banes                    itemView.setIconTintList(mIconTintList);
327153fa9a03422419cd56b7d17def1ae907fc7b5cfChris Banes                    if (mTextAppearanceSet) {
328153fa9a03422419cd56b7d17def1ae907fc7b5cfChris Banes                        itemView.setTextAppearance(itemView.getContext(), mTextAppearance);
329153fa9a03422419cd56b7d17def1ae907fc7b5cfChris Banes                    }
330153fa9a03422419cd56b7d17def1ae907fc7b5cfChris Banes                    if (mTextColor != null) {
331153fa9a03422419cd56b7d17def1ae907fc7b5cfChris Banes                        itemView.setTextColor(mTextColor);
332153fa9a03422419cd56b7d17def1ae907fc7b5cfChris Banes                    }
3331a542ba7235ec038f7ec1ac0ed65f35d29f5c952Yuichi Araki                    itemView.setBackgroundDrawable(mItemBackground != null ?
3341a542ba7235ec038f7ec1ac0ed65f35d29f5c952Yuichi Araki                            mItemBackground.getConstantState().newDrawable() : null);
33501090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                    itemView.initialize(item.getMenuItem(), 0);
33601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                    break;
337ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                case VIEW_TYPE_SUBHEADER:
338ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                    if (convertView == null) {
339ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                        convertView = mLayoutInflater.inflate(
340ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                                R.layout.design_navigation_item_subheader, parent, false);
341ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                    }
342ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                    TextView subHeader = (TextView) convertView;
34301090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                    subHeader.setText(item.getMenuItem().getTitle());
34401090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                    break;
345ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                case VIEW_TYPE_SEPARATOR:
346ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                    if (convertView == null) {
347ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                        convertView = mLayoutInflater.inflate(
348ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                                R.layout.design_navigation_item_separator, parent, false);
349ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                    }
350ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                    convertView.setPadding(0, item.getPaddingTop(), 0,
35160abdeb39630c4c74a4c401e221f0c968caa26f5Yuichi Araki                            item.getPaddingBottom());
35201090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki                    break;
35331a49efe2adb59e31611f6871895a3243d835127Yuichi Araki            }
354ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            return convertView;
355ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        }
35601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
357ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        @Override
358ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        public boolean areAllItemsEnabled() {
359ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            return false;
36001090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        }
36101090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
36201090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        @Override
363ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        public boolean isEnabled(int position) {
364ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            return getItem(position).isEnabled();
36501090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        }
36601090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
367ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        @Override
368ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        public void notifyDataSetChanged() {
3693a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes            prepareMenuItems();
370ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            super.notifyDataSetChanged();
3713a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes        }
3723a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes
3733a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes        /**
3743a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes         * Flattens the visible menu items of {@link #mMenu} into {@link #mItems},
3753a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes         * while inserting separators between items when necessary.
3763a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes         */
3773a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes        private void prepareMenuItems() {
37876bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki            if (mUpdateSuspended) {
37976bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki                return;
38076bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki            }
38142db3143bed767c8e826e69f214672be358078ebYuichi Araki            mUpdateSuspended = true;
3823a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes            mItems.clear();
3833a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes            int currentGroupId = -1;
3843a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes            int currentGroupStart = 0;
3853a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes            boolean currentGroupHasIcon = false;
3863a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes            for (int i = 0, totalSize = mMenu.getVisibleItems().size(); i < totalSize; i++) {
3873a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                MenuItemImpl item = mMenu.getVisibleItems().get(i);
388f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki                if (item.isChecked()) {
389f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki                    setCheckedItem(item);
390f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki                }
391f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki                if (item.isCheckable()) {
392f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki                    item.setExclusiveCheckable(false);
393f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki                }
3943a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                if (item.hasSubMenu()) {
3953a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                    SubMenu subMenu = item.getSubMenu();
3963a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                    if (subMenu.hasVisibleItems()) {
3973a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                        if (i != 0) {
398ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                            mItems.add(NavigationMenuItem.separator(mPaddingSeparator, 0));
3993a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                        }
400ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                        mItems.add(NavigationMenuItem.of(item));
4013a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                        boolean subMenuHasIcon = false;
4023a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                        int subMenuStart = mItems.size();
4033a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                        for (int j = 0, size = subMenu.size(); j < size; j++) {
404f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki                            MenuItemImpl subMenuItem = (MenuItemImpl) subMenu.getItem(j);
4053a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                            if (subMenuItem.isVisible()) {
4063a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                                if (!subMenuHasIcon && subMenuItem.getIcon() != null) {
4073a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                                    subMenuHasIcon = true;
4083a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                                }
409f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki                                if (subMenuItem.isCheckable()) {
410f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki                                    subMenuItem.setExclusiveCheckable(false);
411f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki                                }
412f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki                                if (item.isChecked()) {
413f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki                                    setCheckedItem(item);
414f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki                                }
415ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                                mItems.add(NavigationMenuItem.of(subMenuItem));
4163a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                            }
4173a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                        }
4183a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                        if (subMenuHasIcon) {
4193a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                            appendTransparentIconIfMissing(subMenuStart, mItems.size());
4203a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                        }
4213a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                    }
4223a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                } else {
4233a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                    int groupId = item.getGroupId();
4243a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                    if (groupId != currentGroupId) { // first item in group
4253a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                        currentGroupStart = mItems.size();
4263a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                        currentGroupHasIcon = item.getIcon() != null;
4273a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                        if (i != 0) {
4283a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                            currentGroupStart++;
429ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                            mItems.add(NavigationMenuItem.separator(
43060abdeb39630c4c74a4c401e221f0c968caa26f5Yuichi Araki                                    mPaddingSeparator, mPaddingSeparator));
4313a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                        }
4323a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                    } else if (!currentGroupHasIcon && item.getIcon() != null) {
4333a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                        currentGroupHasIcon = true;
4343a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                        appendTransparentIconIfMissing(currentGroupStart, mItems.size());
4353a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                    }
4363a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                    if (currentGroupHasIcon && item.getIcon() == null) {
4373a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                        item.setIcon(android.R.color.transparent);
4383a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                    }
439ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                    mItems.add(NavigationMenuItem.of(item));
4403a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                    currentGroupId = groupId;
4413a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                }
4423a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes            }
44342db3143bed767c8e826e69f214672be358078ebYuichi Araki            mUpdateSuspended = false;
4443a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes        }
4453a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes
4463a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes        private void appendTransparentIconIfMissing(int startIndex, int endIndex) {
4473a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes            for (int i = startIndex; i < endIndex; i++) {
448ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                MenuItem item = mItems.get(i).getMenuItem();
4493a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                if (item.getIcon() == null) {
4503a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                    if (mTransparentIcon == null) {
4513a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                        mTransparentIcon = new ColorDrawable(android.R.color.transparent);
4523a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                    }
4533a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                    item.setIcon(mTransparentIcon);
4543a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes                }
4553a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes            }
4563a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes        }
45776bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki
458f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki        public void setCheckedItem(MenuItemImpl checkedItem) {
459f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki            if (mCheckedItem == checkedItem || !checkedItem.isCheckable()) {
460f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki                return;
461f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki            }
462f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki            if (mCheckedItem != null) {
463f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki                mCheckedItem.setChecked(false);
464f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki            }
465f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki            mCheckedItem = checkedItem;
466f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki            checkedItem.setChecked(true);
467f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki        }
468f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki
46976bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki        public Bundle createInstanceState() {
47076bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki            Bundle state = new Bundle();
471024b36390fce843107b0916f0c3468e5a67a212aYuichi Araki            if (mCheckedItem != null) {
472024b36390fce843107b0916f0c3468e5a67a212aYuichi Araki                state.putInt(STATE_CHECKED_ITEM, mCheckedItem.getItemId());
473024b36390fce843107b0916f0c3468e5a67a212aYuichi Araki            }
47436d347c02fa8da71ccd69634484be8156fa0085bYuichi Araki            // Store the states of the action views.
47536d347c02fa8da71ccd69634484be8156fa0085bYuichi Araki            SparseArray<ParcelableSparseArray> actionViewStates = new SparseArray<>();
47636d347c02fa8da71ccd69634484be8156fa0085bYuichi Araki            for (NavigationMenuItem navigationMenuItem : mItems) {
477ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                MenuItemImpl item = navigationMenuItem.getMenuItem();
478ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                View actionView = item != null ? item.getActionView() : null;
479ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                if (actionView != null) {
480ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                    ParcelableSparseArray container = new ParcelableSparseArray();
481ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                    actionView.saveHierarchyState(container);
482ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                    actionViewStates.put(item.getItemId(), container);
48336d347c02fa8da71ccd69634484be8156fa0085bYuichi Araki                }
48436d347c02fa8da71ccd69634484be8156fa0085bYuichi Araki            }
48536d347c02fa8da71ccd69634484be8156fa0085bYuichi Araki            state.putSparseParcelableArray(STATE_ACTION_VIEWS, actionViewStates);
48676bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki            return state;
48776bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki        }
48876bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki
48976bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki        public void restoreInstanceState(Bundle state) {
490f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki            int checkedItem = state.getInt(STATE_CHECKED_ITEM, 0);
491f9b8005bf607feddd9b482f817bd68c46739e4f1Yuichi Araki            if (checkedItem != 0) {
49276bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki                mUpdateSuspended = true;
49376bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki                for (NavigationMenuItem item : mItems) {
494ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                    MenuItemImpl menuItem = item.getMenuItem();
495ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                    if (menuItem != null && menuItem.getItemId() == checkedItem) {
496ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                        setCheckedItem(menuItem);
497ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                        break;
49876bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki                    }
49976bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki                }
50076bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki                mUpdateSuspended = false;
50176bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki                prepareMenuItems();
50276bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki            }
50336d347c02fa8da71ccd69634484be8156fa0085bYuichi Araki            // Restore the states of the action views.
50436d347c02fa8da71ccd69634484be8156fa0085bYuichi Araki            SparseArray<ParcelableSparseArray> actionViewStates = state
50536d347c02fa8da71ccd69634484be8156fa0085bYuichi Araki                    .getSparseParcelableArray(STATE_ACTION_VIEWS);
50636d347c02fa8da71ccd69634484be8156fa0085bYuichi Araki            for (NavigationMenuItem navigationMenuItem : mItems) {
507ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                MenuItemImpl item = navigationMenuItem.getMenuItem();
508ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                View actionView = item != null ? item.getActionView() : null;
509ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                if (actionView != null) {
510ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes                    actionView.restoreHierarchyState(actionViewStates.get(item.getItemId()));
51136d347c02fa8da71ccd69634484be8156fa0085bYuichi Araki                }
51236d347c02fa8da71ccd69634484be8156fa0085bYuichi Araki            }
51376bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki        }
51476bd4d2c1173100ab73c4f27dc42dd917c48915fYuichi Araki
515cc7a09fc0018e348027151daecf581b1d1b78f11Yuichi Araki        public void setUpdateSuspended(boolean updateSuspended) {
516cc7a09fc0018e348027151daecf581b1d1b78f11Yuichi Araki            mUpdateSuspended = updateSuspended;
517cc7a09fc0018e348027151daecf581b1d1b78f11Yuichi Araki        }
518cc7a09fc0018e348027151daecf581b1d1b78f11Yuichi Araki
51901090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    }
52001090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
52101090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki    /**
522ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes     * Wraps {@link MenuItemImpl}. This allows separators to be counted as items in list.
523e7b2c26d2ffadc94dc6ee043ab12e03201e1bf95Yuichi Araki     */
524ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes    private static class NavigationMenuItem {
52560abdeb39630c4c74a4c401e221f0c968caa26f5Yuichi Araki
526ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        /** The item; null for separators */
527e7b2c26d2ffadc94dc6ee043ab12e03201e1bf95Yuichi Araki        private final MenuItemImpl mMenuItem;
52860abdeb39630c4c74a4c401e221f0c968caa26f5Yuichi Araki
529ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        /** Padding top; used only for separators */
530e7b2c26d2ffadc94dc6ee043ab12e03201e1bf95Yuichi Araki        private final int mPaddingTop;
531e7b2c26d2ffadc94dc6ee043ab12e03201e1bf95Yuichi Araki
532ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        /** Padding bottom; used only for separators */
533e7b2c26d2ffadc94dc6ee043ab12e03201e1bf95Yuichi Araki        private final int mPaddingBottom;
534e7b2c26d2ffadc94dc6ee043ab12e03201e1bf95Yuichi Araki
535ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        private NavigationMenuItem(MenuItemImpl item, int paddingTop, int paddingBottom) {
536ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            mMenuItem = item;
537e7b2c26d2ffadc94dc6ee043ab12e03201e1bf95Yuichi Araki            mPaddingTop = paddingTop;
538e7b2c26d2ffadc94dc6ee043ab12e03201e1bf95Yuichi Araki            mPaddingBottom = paddingBottom;
53960abdeb39630c4c74a4c401e221f0c968caa26f5Yuichi Araki        }
54060abdeb39630c4c74a4c401e221f0c968caa26f5Yuichi Araki
541ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        public static NavigationMenuItem of(MenuItemImpl item) {
542ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            return new NavigationMenuItem(item, 0, 0);
543ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        }
544ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes
545ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        public static NavigationMenuItem separator(int paddingTop, int paddingBottom) {
546ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            return new NavigationMenuItem(null, paddingTop, paddingBottom);
547ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        }
548ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes
549ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        public boolean isSeparator() {
550ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            return mMenuItem == null;
551ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        }
552ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes
55360abdeb39630c4c74a4c401e221f0c968caa26f5Yuichi Araki        public int getPaddingTop() {
55460abdeb39630c4c74a4c401e221f0c968caa26f5Yuichi Araki            return mPaddingTop;
55560abdeb39630c4c74a4c401e221f0c968caa26f5Yuichi Araki        }
55660abdeb39630c4c74a4c401e221f0c968caa26f5Yuichi Araki
55760abdeb39630c4c74a4c401e221f0c968caa26f5Yuichi Araki        public int getPaddingBottom() {
55860abdeb39630c4c74a4c401e221f0c968caa26f5Yuichi Araki            return mPaddingBottom;
55901090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki        }
56001090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
561ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        public MenuItemImpl getMenuItem() {
562ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            return mMenuItem;
563ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        }
564ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes
565ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        public boolean isEnabled() {
566ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            // Separators and subheaders never respond to click
567ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes            return mMenuItem != null && !mMenuItem.hasSubMenu() && mMenuItem.isEnabled();
568ca2f07c9cc83b98d73a18da7177044ee147ffb94Chris Banes        }
56901090f9556e7518c9ee206de6efe42de9003f6f5Yuichi Araki
57031a49efe2adb59e31611f6871895a3243d835127Yuichi Araki    }
57131a49efe2adb59e31611f6871895a3243d835127Yuichi Araki
57231a49efe2adb59e31611f6871895a3243d835127Yuichi Araki}
573