ActionBarLayout.java revision 674af92fd3a618695448ff88568b03390e90bc66
114bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta/*
214bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta * Copyright (C) 2014 The Android Open Source Project
314bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta *
414bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta * Licensed under the Apache License, Version 2.0 (the "License");
514bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta * you may not use this file except in compliance with the License.
614bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta * You may obtain a copy of the License at
714bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta *
814bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta *      http://www.apache.org/licenses/LICENSE-2.0
914bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta *
1014bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta * Unless required by applicable law or agreed to in writing, software
1114bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta * distributed under the License is distributed on an "AS IS" BASIS,
1214bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1314bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta * See the License for the specific language governing permissions and
1414bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta * limitations under the License.
1514bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta */
1614bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta
1714bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Guptapackage com.android.layoutlib.bridge.bars;
1814bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta
19929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Guptaimport com.android.annotations.NonNull;
20929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Guptaimport com.android.annotations.Nullable;
2114bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Guptaimport com.android.ide.common.rendering.api.ActionBarCallback;
2214bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Guptaimport com.android.ide.common.rendering.api.ActionBarCallback.HomeButtonStyle;
2314bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Guptaimport com.android.ide.common.rendering.api.RenderResources;
2414bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Guptaimport com.android.ide.common.rendering.api.ResourceValue;
2514bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Guptaimport com.android.ide.common.rendering.api.SessionParams;
26674af92fd3a618695448ff88568b03390e90bc66Deepanshu Guptaimport com.android.ide.common.rendering.api.SystemViewCookie;
27929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Guptaimport com.android.internal.R;
2814bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Guptaimport com.android.internal.app.WindowDecorActionBar;
29674af92fd3a618695448ff88568b03390e90bc66Deepanshu Guptaimport com.android.internal.util.Predicate;
3014bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Guptaimport com.android.internal.view.menu.MenuBuilder;
31929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Guptaimport com.android.internal.view.menu.MenuItemImpl;
32929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Guptaimport com.android.internal.widget.ActionBarAccessor;
3314bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Guptaimport com.android.internal.widget.ActionBarContainer;
3414bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Guptaimport com.android.internal.widget.ActionBarView;
3514bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Guptaimport com.android.layoutlib.bridge.android.BridgeContext;
3614bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Guptaimport com.android.layoutlib.bridge.impl.ResourceHelper;
3714bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Guptaimport com.android.resources.ResourceType;
3814bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta
3914bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Guptaimport android.app.ActionBar;
4014bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Guptaimport android.app.ActionBar.Tab;
4114bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Guptaimport android.app.ActionBar.TabListener;
4214bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Guptaimport android.app.FragmentTransaction;
4314bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Guptaimport android.content.Context;
44929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Guptaimport android.content.res.TypedArray;
4514bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Guptaimport android.graphics.drawable.Drawable;
46929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Guptaimport android.util.DisplayMetrics;
47929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Guptaimport android.util.TypedValue;
4814bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Guptaimport android.view.Gravity;
4914bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Guptaimport android.view.LayoutInflater;
5014bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Guptaimport android.view.MenuInflater;
51929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Guptaimport android.view.View;
52929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Guptaimport android.view.ViewGroup;
53929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Guptaimport android.widget.FrameLayout;
5414bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Guptaimport android.widget.LinearLayout;
55929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Guptaimport android.widget.ListAdapter;
56929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Guptaimport android.widget.ListView;
57929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Guptaimport android.widget.RelativeLayout;
5814bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta
5914bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Guptaimport java.util.ArrayList;
6014bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta
61674af92fd3a618695448ff88568b03390e90bc66Deepanshu Guptaimport static com.android.ide.common.rendering.api.SystemViewCookie.ACTION_BAR_OVERFLOW;
62674af92fd3a618695448ff88568b03390e90bc66Deepanshu Gupta
63929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta/**
64929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta * A layout representing the action bar.
65929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta */
6614bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Guptapublic class ActionBarLayout extends LinearLayout {
6714bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta
6814bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta    // Store another reference to the context so that we don't have to cast it repeatedly.
69929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    @NonNull private final BridgeContext mBridgeContext;
70929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    @NonNull private final Context mThemedContext;
71929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta
72929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    @NonNull private final ActionBar mActionBar;
73929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta
74929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    // Data for Action Bar.
75929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    @Nullable private final String mIcon;
76929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    @Nullable private final String mTitle;
77929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    @Nullable private final String mSubTitle;
7814bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta    private final boolean mSplit;
7914bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta    private final boolean mShowHomeAsUp;
8014bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta    private final int mNavMode;
8114bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta
82929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    // Helper fields.
83929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    @NonNull private final MenuBuilder mMenuBuilder;
84929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    private final int mPopupMaxWidth;
85929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    @NonNull private final RenderResources res;
86929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    @Nullable private final ActionBarView mActionBarView;
87929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    @Nullable private FrameLayout mContentRoot;
88929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    @NonNull private final ActionBarCallback mCallback;
8914bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta
90929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    // A fake parent for measuring views.
91929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    @Nullable private ViewGroup mMeasureParent;
9214bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta
93929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    public ActionBarLayout(@NonNull BridgeContext context, @NonNull SessionParams params) {
94929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta
95929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        super(context);
9614bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta        setOrientation(LinearLayout.HORIZONTAL);
9714bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta        setGravity(Gravity.CENTER_VERTICAL);
9814bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta
99929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        // Inflate action bar layout.
100929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        LayoutInflater.from(context).inflate(R.layout.screen_action_bar, this,
101929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta                true /*attachToRoot*/);
10214bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta        mActionBar = new WindowDecorActionBar(this);
10314bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta
104929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        // Set contexts.
105929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        mBridgeContext = context;
106929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        mThemedContext = mActionBar.getThemedContext();
10714bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta
108929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        // Set data for action bar.
109929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        mCallback = params.getProjectCallback().getActionBarCallback();
110929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        mIcon = params.getAppIcon();
111929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        mTitle = params.getAppLabel();
112929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        // Split Action Bar when the screen size is narrow and the application requests split action
113929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        // bar when narrow.
114929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        mSplit = context.getResources().getBoolean(R.bool.split_action_bar_is_narrow) &&
115929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta                mCallback.getSplitActionBarWhenNarrow();
116929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        mNavMode = mCallback.getNavigationMode();
117929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        // TODO: Support Navigation Drawer Indicator.
118929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        mShowHomeAsUp = mCallback.getHomeButtonStyle() == HomeButtonStyle.SHOW_HOME_AS_UP;
119929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        mSubTitle = mCallback.getSubTitle();
120929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta
121929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta
122929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        // Set helper fields.
123929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        mMenuBuilder = new MenuBuilder(mThemedContext);
124929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        res = mBridgeContext.getRenderResources();
125929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        mPopupMaxWidth = Math.max(mBridgeContext.getMetrics().widthPixels / 2,
126929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta                mThemedContext.getResources().getDimensionPixelSize(
127929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta                        R.dimen.config_prefDialogWidth));
128929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        mActionBarView = (ActionBarView) findViewById(R.id.action_bar);
129929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        mContentRoot = (FrameLayout) findViewById(android.R.id.content);
130929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta
131929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        setupActionBar();
13214bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta    }
13314bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta
134929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    /**
135929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta     * Sets up the action bar by filling the appropriate data.
136929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta     */
137929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    private void setupActionBar() {
138929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        // Add title and sub title.
13914bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta        ResourceValue titleValue = res.findResValue(mTitle, false /*isFramework*/);
14014bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta        if (titleValue != null && titleValue.getValue() != null) {
14114bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta            mActionBar.setTitle(titleValue.getValue());
14214bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta        } else {
14314bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta            mActionBar.setTitle(mTitle);
14414bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta        }
14514bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta        if (mSubTitle != null) {
14614bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta            mActionBar.setSubtitle(mSubTitle);
14714bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta        }
148929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta
149929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        // Add show home as up icon.
15014bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta        if (mShowHomeAsUp) {
15114bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta            mActionBar.setDisplayOptions(0xFF, ActionBar.DISPLAY_HOME_AS_UP);
15214bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta        }
15314bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta
154929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        // Set the navigation mode.
15514bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta        mActionBar.setNavigationMode(mNavMode);
15614bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta        if (mNavMode == ActionBar.NAVIGATION_MODE_TABS) {
157929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            setupTabs(3);
158929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        }
159929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta
160929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        if (mActionBarView != null) {
161929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            // If the action bar style doesn't specify an icon, set the icon obtained from the session
162929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            // params.
163929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            if (!mActionBarView.hasIcon() && mIcon != null) {
164929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta                Drawable iconDrawable = getDrawable(mIcon, false /*isFramework*/);
165929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta                if (iconDrawable != null) {
166929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta                    mActionBar.setIcon(iconDrawable);
167929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta                }
168929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            }
169929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta
170929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            // Set action bar to be split, if needed.
171674af92fd3a618695448ff88568b03390e90bc66Deepanshu Gupta            ActionBarContainer splitView = (ActionBarContainer) findViewById(R.id.split_action_bar);
172674af92fd3a618695448ff88568b03390e90bc66Deepanshu Gupta            mActionBarView.setSplitView(splitView);
173929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            mActionBarView.setSplitActionBar(mSplit);
174929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta
175929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            inflateMenus();
176674af92fd3a618695448ff88568b03390e90bc66Deepanshu Gupta
177674af92fd3a618695448ff88568b03390e90bc66Deepanshu Gupta            // Find if the Overflow Menu Button (the three dots) exists. If yes,
178674af92fd3a618695448ff88568b03390e90bc66Deepanshu Gupta            // add the view cookie.
179674af92fd3a618695448ff88568b03390e90bc66Deepanshu Gupta            Predicate<View> overflowMenuButtonTest = new Predicate<View>() {
180674af92fd3a618695448ff88568b03390e90bc66Deepanshu Gupta                @Override
181674af92fd3a618695448ff88568b03390e90bc66Deepanshu Gupta                public boolean apply(View view) {
182674af92fd3a618695448ff88568b03390e90bc66Deepanshu Gupta                    return view.getClass().getName()
183674af92fd3a618695448ff88568b03390e90bc66Deepanshu Gupta                            .equals("android.widget.ActionMenuPresenter$OverflowMenuButton");
184674af92fd3a618695448ff88568b03390e90bc66Deepanshu Gupta                }
185674af92fd3a618695448ff88568b03390e90bc66Deepanshu Gupta            };
186674af92fd3a618695448ff88568b03390e90bc66Deepanshu Gupta            View overflowMenu = null;
187674af92fd3a618695448ff88568b03390e90bc66Deepanshu Gupta            if (mSplit) {
188674af92fd3a618695448ff88568b03390e90bc66Deepanshu Gupta                if (splitView != null) {
189674af92fd3a618695448ff88568b03390e90bc66Deepanshu Gupta                    overflowMenu = splitView.findViewByPredicate(overflowMenuButtonTest);
190674af92fd3a618695448ff88568b03390e90bc66Deepanshu Gupta                }
191674af92fd3a618695448ff88568b03390e90bc66Deepanshu Gupta            }
192674af92fd3a618695448ff88568b03390e90bc66Deepanshu Gupta            else {
193674af92fd3a618695448ff88568b03390e90bc66Deepanshu Gupta                overflowMenu = mActionBarView.findViewByPredicate(overflowMenuButtonTest);
194674af92fd3a618695448ff88568b03390e90bc66Deepanshu Gupta            }
195674af92fd3a618695448ff88568b03390e90bc66Deepanshu Gupta            if (overflowMenu != null) {
196674af92fd3a618695448ff88568b03390e90bc66Deepanshu Gupta                mBridgeContext.addViewKey(overflowMenu, new SystemViewCookie(ACTION_BAR_OVERFLOW));
197674af92fd3a618695448ff88568b03390e90bc66Deepanshu Gupta            }
19814bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta        }
19914bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta    }
20014bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta
201929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    /**
202929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta     * Gets the menus to add to the action bar from the callback, resolves them, inflates them and
203929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta     * adds them to the action bar.
204929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta     */
205929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    private void inflateMenus() {
206929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        if (mActionBarView == null) {
20714bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta            return;
20814bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta        }
209929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        final MenuInflater inflater = new MenuInflater(mThemedContext);
210929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        for (String name : mCallback.getMenuIdNames()) {
211929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            if (mBridgeContext.getRenderResources().getProjectResource(ResourceType.MENU, name)
212929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta                    != null) {
213929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta                int id = mBridgeContext.getProjectResourceValue(ResourceType.MENU, name, -1);
214929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta                if (id > -1) {
215929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta                    inflater.inflate(id, mMenuBuilder);
216929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta                }
217929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            }
21814bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta        }
219929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        mActionBarView.setMenu(mMenuBuilder, null /*callback*/);
22014bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta    }
22114bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta
22214bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta    // TODO: Use an adapter, like List View to set up tabs.
223929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    private void setupTabs(int num) {
22414bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta        for (int i = 1; i <= num; i++) {
225929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            Tab tab = mActionBar.newTab().setText("Tab" + i).setTabListener(new TabListener() {
22614bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta                @Override
22714bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta                public void onTabUnselected(Tab t, FragmentTransaction ft) {
22814bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta                    // pass
22914bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta                }
23014bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta                @Override
23114bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta                public void onTabSelected(Tab t, FragmentTransaction ft) {
23214bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta                    // pass
23314bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta                }
23414bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta                @Override
23514bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta                public void onTabReselected(Tab t, FragmentTransaction ft) {
23614bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta                    // pass
23714bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta                }
23814bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta            });
23914bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta            mActionBar.addTab(tab);
24014bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta        }
24114bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta    }
24214bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta
243929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    @Nullable
244929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    private Drawable getDrawable(@NonNull String name, boolean isFramework) {
24514bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta        ResourceValue value = res.findResValue(name, isFramework);
24614bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta        value = res.resolveResValue(value);
24714bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta        if (value != null) {
248929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            return ResourceHelper.getDrawable(value, mBridgeContext);
24914bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta        }
25014bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta        return null;
25114bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta    }
252929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta
253929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    /**
254929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta     * Creates a Popup and adds it to the content frame. It also adds another {@link FrameLayout} to
255929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta     * the content frame which shall serve as the new content root.
256929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta     */
257929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    public void createMenuPopup() {
258929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        assert mContentRoot != null && findViewById(android.R.id.content) == mContentRoot
259929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta                : "Action Bar Menus have already been created.";
260929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta
261929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        if (!isOverflowPopupNeeded()) {
262929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            return;
263929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        }
264929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta
265929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        // Create a layout to hold the menus and the user's content.
266929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        RelativeLayout layout = new RelativeLayout(mThemedContext);
267929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
268929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta                LayoutParams.MATCH_PARENT));
269929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        mContentRoot.addView(layout);
270929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        // Create a layout for the user's content.
271929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        FrameLayout contentRoot = new FrameLayout(mBridgeContext);
272929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        contentRoot.setLayoutParams(new LayoutParams(
273929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
274929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        // Add contentRoot and menus to the layout.
275929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        layout.addView(contentRoot);
276929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        layout.addView(createMenuView());
277929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        // ContentRoot is now the view we just created.
278929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        mContentRoot = contentRoot;
279929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    }
280929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta
281929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    /**
282929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta     * Returns a {@link LinearLayout} containing the menu list view to be embedded in a
283929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta     * {@link RelativeLayout}
284929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta     */
285929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    @NonNull
286929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    private View createMenuView() {
287929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        DisplayMetrics metrics = mBridgeContext.getMetrics();
288929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        OverflowMenuAdapter adapter = new OverflowMenuAdapter(mMenuBuilder, mThemedContext);
289929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta
290929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        LinearLayout layout = new LinearLayout(mThemedContext);
291929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
292929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta                measureContentWidth(adapter), LayoutParams.WRAP_CONTENT);
293929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        layoutParams.addRule(RelativeLayout.ALIGN_PARENT_END);
294929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        if (mSplit) {
295929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
296929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            // TODO: Find correct value instead of hardcoded 10dp.
297929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            layoutParams.bottomMargin = getPixelValue("-10dp", metrics);
298929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        } else {
299929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            layoutParams.topMargin = getPixelValue("-10dp", metrics);
300929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        }
301929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        layout.setLayoutParams(layoutParams);
302929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        final TypedArray a = mThemedContext.obtainStyledAttributes(null,
303929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta                R.styleable.PopupWindow, R.attr.popupMenuStyle, 0);
304929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        layout.setBackground(a.getDrawable(R.styleable.PopupWindow_popupBackground));
305929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        layout.setDividerDrawable(a.getDrawable(R.attr.actionBarDivider));
306929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        a.recycle();
307929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        layout.setOrientation(LinearLayout.VERTICAL);
308929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        layout.setDividerPadding(getPixelValue("12dp", metrics));
309929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        layout.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE);
310929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta
311929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        ListView listView = new ListView(mThemedContext, null, R.attr.dropDownListViewStyle);
312929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        listView.setAdapter(adapter);
313929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        layout.addView(listView);
314929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        return layout;
315929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    }
316929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta
317929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    private boolean isOverflowPopupNeeded() {
318929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        boolean needed = mCallback.isOverflowPopupNeeded();
319929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        if (!needed) {
320929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            return false;
321929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        }
322929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        // Copied from android.widget.ActionMenuPresenter.updateMenuView()
323929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        ArrayList<MenuItemImpl> menus = mMenuBuilder.getNonActionItems();
324929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        if (ActionBarAccessor.getActionMenuPresenter(mActionBarView).isOverflowReserved() &&
325929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta                menus != null) {
326929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            final int count = menus.size();
327929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            if (count == 1) {
328929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta                needed = !menus.get(0).isActionViewExpanded();
329929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            } else {
330929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta                needed = count > 0;
331929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            }
332929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        }
333929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        return needed;
334929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    }
335929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta
336929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    @Nullable
337929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    public FrameLayout getContentRoot() {
338929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        return mContentRoot;
339929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    }
340929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta
341929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    // Copied from com.android.internal.view.menu.MenuPopHelper.measureContentWidth()
342929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    private int measureContentWidth(@NonNull ListAdapter adapter) {
343929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        // Menus don't tend to be long, so this is more sane than it looks.
344929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        int maxWidth = 0;
345929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        View itemView = null;
346929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        int itemType = 0;
347929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta
348929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
349929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
350929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        final int count = adapter.getCount();
351929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        for (int i = 0; i < count; i++) {
352929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            final int positionType = adapter.getItemViewType(i);
353929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            if (positionType != itemType) {
354929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta                itemType = positionType;
355929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta                itemView = null;
356929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            }
357929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta
358929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            if (mMeasureParent == null) {
359929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta                mMeasureParent = new FrameLayout(mThemedContext);
360929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            }
361929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta
362929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            itemView = adapter.getView(i, itemView, mMeasureParent);
363929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            itemView.measure(widthMeasureSpec, heightMeasureSpec);
364929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta
365929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            final int itemWidth = itemView.getMeasuredWidth();
366929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            if (itemWidth >= mPopupMaxWidth) {
367929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta                return mPopupMaxWidth;
368929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            } else if (itemWidth > maxWidth) {
369929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta                maxWidth = itemWidth;
370929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta            }
371929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        }
372929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta
373929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        return maxWidth;
374929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    }
375929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta
376929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    private int getPixelValue(@NonNull String value, @NonNull DisplayMetrics metrics) {
377929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        TypedValue typedValue = ResourceHelper.getValue(null, value, false /*requireUnit*/);
378929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta        return (int) typedValue.getDimension(metrics);
379929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta    }
380929eea6bc1824bf98d244550c0984ecf8ea98811Deepanshu Gupta
38114bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta}
382