ActionBarView.java revision c29f4e52c3377924df26910cce3ff26278d1f484
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.internal.widget;
18
19import com.android.internal.R;
20import com.android.internal.view.menu.ActionMenuItem;
21import com.android.internal.view.menu.ActionMenuPresenter;
22import com.android.internal.view.menu.ActionMenuView;
23import com.android.internal.view.menu.MenuBuilder;
24import com.android.internal.view.menu.MenuItemImpl;
25import com.android.internal.view.menu.MenuPresenter;
26import com.android.internal.view.menu.MenuView;
27import com.android.internal.view.menu.SubMenuBuilder;
28
29import android.app.ActionBar;
30import android.app.ActionBar.OnNavigationListener;
31import android.app.Activity;
32import android.content.Context;
33import android.content.pm.ApplicationInfo;
34import android.content.pm.PackageManager;
35import android.content.pm.PackageManager.NameNotFoundException;
36import android.content.res.Resources;
37import android.content.res.TypedArray;
38import android.graphics.drawable.Drawable;
39import android.os.Parcel;
40import android.os.Parcelable;
41import android.text.TextUtils;
42import android.util.AttributeSet;
43import android.util.DisplayMetrics;
44import android.util.Log;
45import android.view.Gravity;
46import android.view.LayoutInflater;
47import android.view.Menu;
48import android.view.MenuItem;
49import android.view.View;
50import android.view.ViewGroup;
51import android.view.ViewParent;
52import android.view.Window;
53import android.widget.AdapterView;
54import android.widget.FrameLayout;
55import android.widget.ImageView;
56import android.widget.LinearLayout;
57import android.widget.ProgressBar;
58import android.widget.Spinner;
59import android.widget.SpinnerAdapter;
60import android.widget.TextView;
61
62/**
63 * @hide
64 */
65public class ActionBarView extends AbsActionBarView {
66    private static final String TAG = "ActionBarView";
67
68    /**
69     * Display options applied by default
70     */
71    public static final int DISPLAY_DEFAULT = 0;
72
73    /**
74     * Display options that require re-layout as opposed to a simple invalidate
75     */
76    private static final int DISPLAY_RELAYOUT_MASK =
77            ActionBar.DISPLAY_SHOW_HOME |
78            ActionBar.DISPLAY_USE_LOGO |
79            ActionBar.DISPLAY_HOME_AS_UP |
80            ActionBar.DISPLAY_SHOW_CUSTOM |
81            ActionBar.DISPLAY_SHOW_TITLE;
82
83    private static final int DEFAULT_CUSTOM_GRAVITY = Gravity.LEFT | Gravity.CENTER_VERTICAL;
84
85    private int mContentHeight;
86
87    private int mNavigationMode;
88    private int mDisplayOptions = ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_HOME_AS_UP;
89    private CharSequence mTitle;
90    private CharSequence mSubtitle;
91    private Drawable mIcon;
92    private Drawable mLogo;
93
94    private HomeView mHomeLayout;
95    private HomeView mExpandedHomeLayout;
96    private LinearLayout mTitleLayout;
97    private TextView mTitleView;
98    private TextView mSubtitleView;
99    private View mTitleUpView;
100
101    private Spinner mSpinner;
102    private LinearLayout mListNavLayout;
103    private ScrollingTabContainerView mTabScrollView;
104    private View mCustomNavView;
105    private ProgressBar mProgressView;
106    private ProgressBar mIndeterminateProgressView;
107
108    private int mProgressBarPadding;
109    private int mItemPadding;
110
111    private int mTitleStyleRes;
112    private int mSubtitleStyleRes;
113    private int mProgressStyle;
114    private int mIndeterminateProgressStyle;
115
116    private boolean mSplitActionBar;
117    private boolean mUserTitle;
118    private boolean mIncludeTabs;
119    private boolean mIsCollapsable;
120    private boolean mIsCollapsed;
121
122    private MenuBuilder mOptionsMenu;
123
124    private ActionBarContextView mContextView;
125
126    private ActionMenuItem mLogoNavItem;
127
128    private SpinnerAdapter mSpinnerAdapter;
129    private OnNavigationListener mCallback;
130
131    private Runnable mTabSelector;
132
133    private ExpandedActionViewMenuPresenter mExpandedMenuPresenter;
134    View mExpandedActionView;
135
136    private final AdapterView.OnItemSelectedListener mNavItemSelectedListener =
137            new AdapterView.OnItemSelectedListener() {
138        public void onItemSelected(AdapterView parent, View view, int position, long id) {
139            if (mCallback != null) {
140                mCallback.onNavigationItemSelected(position, id);
141            }
142        }
143        public void onNothingSelected(AdapterView parent) {
144            // Do nothing
145        }
146    };
147
148    private final OnClickListener mExpandedActionViewUpListener = new OnClickListener() {
149        @Override
150        public void onClick(View v) {
151            final MenuItemImpl item = mExpandedMenuPresenter.mCurrentExpandedItem;
152            if (item != null) {
153                item.collapseActionView();
154            }
155        }
156    };
157
158    private final OnClickListener mUpClickListener = new OnClickListener() {
159        public void onClick(View v) {
160            Context context = getContext();
161            if (context instanceof Activity) {
162                Activity activity = (Activity) context;
163                activity.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, mLogoNavItem);
164            }
165        }
166    };
167
168    public ActionBarView(Context context, AttributeSet attrs) {
169        super(context, attrs);
170
171        // Background is always provided by the container.
172        setBackgroundResource(0);
173
174        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ActionBar);
175
176        ApplicationInfo appInfo = context.getApplicationInfo();
177        PackageManager pm = context.getPackageManager();
178        mNavigationMode = a.getInt(R.styleable.ActionBar_navigationMode,
179                ActionBar.NAVIGATION_MODE_STANDARD);
180        mTitle = a.getText(R.styleable.ActionBar_title);
181        mSubtitle = a.getText(R.styleable.ActionBar_subtitle);
182
183        mLogo = a.getDrawable(R.styleable.ActionBar_logo);
184        if (mLogo == null) {
185            if (context instanceof Activity) {
186                try {
187                    mLogo = pm.getActivityLogo(((Activity) context).getComponentName());
188                } catch (NameNotFoundException e) {
189                    Log.e(TAG, "Activity component name not found!", e);
190                }
191            }
192            if (mLogo == null) {
193                mLogo = appInfo.loadLogo(pm);
194            }
195        }
196
197        mIcon = a.getDrawable(R.styleable.ActionBar_icon);
198        if (mIcon == null) {
199            if (context instanceof Activity) {
200                try {
201                    mIcon = pm.getActivityIcon(((Activity) context).getComponentName());
202                } catch (NameNotFoundException e) {
203                    Log.e(TAG, "Activity component name not found!", e);
204                }
205            }
206            if (mIcon == null) {
207                mIcon = appInfo.loadIcon(pm);
208            }
209        }
210
211        final LayoutInflater inflater = LayoutInflater.from(context);
212
213        final int homeResId = a.getResourceId(
214                com.android.internal.R.styleable.ActionBar_homeLayout,
215                com.android.internal.R.layout.action_bar_home);
216
217        mHomeLayout = (HomeView) inflater.inflate(homeResId, this, false);
218
219        mExpandedHomeLayout = (HomeView) inflater.inflate(homeResId, this, false);
220        mExpandedHomeLayout.setUp(true);
221        mExpandedHomeLayout.setOnClickListener(mExpandedActionViewUpListener);
222
223        mTitleStyleRes = a.getResourceId(R.styleable.ActionBar_titleTextStyle, 0);
224        mSubtitleStyleRes = a.getResourceId(R.styleable.ActionBar_subtitleTextStyle, 0);
225        mProgressStyle = a.getResourceId(R.styleable.ActionBar_progressBarStyle, 0);
226        mIndeterminateProgressStyle = a.getResourceId(
227                R.styleable.ActionBar_indeterminateProgressStyle, 0);
228
229        mProgressBarPadding = a.getDimensionPixelOffset(R.styleable.ActionBar_progressBarPadding, 0);
230        mItemPadding = a.getDimensionPixelOffset(R.styleable.ActionBar_itemPadding, 0);
231
232        setDisplayOptions(a.getInt(R.styleable.ActionBar_displayOptions, DISPLAY_DEFAULT));
233
234        final int customNavId = a.getResourceId(R.styleable.ActionBar_customNavigationLayout, 0);
235        if (customNavId != 0) {
236            mCustomNavView = (View) inflater.inflate(customNavId, this, false);
237            mNavigationMode = ActionBar.NAVIGATION_MODE_STANDARD;
238            setDisplayOptions(mDisplayOptions | ActionBar.DISPLAY_SHOW_CUSTOM);
239        }
240
241        mContentHeight = a.getLayoutDimension(R.styleable.ActionBar_height, 0);
242
243        a.recycle();
244
245        mLogoNavItem = new ActionMenuItem(context, 0, android.R.id.home, 0, 0, mTitle);
246        mHomeLayout.setOnClickListener(mUpClickListener);
247        mHomeLayout.setClickable(true);
248        mHomeLayout.setFocusable(true);
249    }
250
251    @Override
252    public void onDetachedFromWindow() {
253        super.onDetachedFromWindow();
254        removeCallbacks(mTabSelector);
255    }
256
257    @Override
258    public boolean shouldDelayChildPressedState() {
259        return false;
260    }
261
262    public void initProgress() {
263        mProgressView = new ProgressBar(mContext, null, 0, mProgressStyle);
264        mProgressView.setId(R.id.progress_horizontal);
265        mProgressView.setMax(10000);
266        addView(mProgressView);
267    }
268
269    public void initIndeterminateProgress() {
270        mIndeterminateProgressView = new ProgressBar(mContext, null, 0,
271                mIndeterminateProgressStyle);
272        mIndeterminateProgressView.setId(R.id.progress_circular);
273        addView(mIndeterminateProgressView);
274    }
275
276    public void setContentHeight(int height) {
277        mContentHeight = height;
278        requestLayout();
279    }
280
281    public int getContentHeight() {
282        return mContentHeight;
283    }
284
285    public void setSplitActionBar(boolean splitActionBar) {
286        if (mSplitActionBar != splitActionBar) {
287            if (mMenuView != null) {
288                if (splitActionBar) {
289                    removeView(mMenuView);
290                    if (mSplitView != null) {
291                        mSplitView.addView(mMenuView);
292                    }
293                } else {
294                    addView(mMenuView);
295                }
296            }
297            mSplitActionBar = splitActionBar;
298        }
299    }
300
301    public boolean isSplitActionBar() {
302        return mSplitActionBar;
303    }
304
305    public boolean hasEmbeddedTabs() {
306        return mIncludeTabs;
307    }
308
309    public void setEmbeddedTabView(ScrollingTabContainerView tabs) {
310        if (mTabScrollView != null) {
311            removeView(mTabScrollView);
312        }
313        mTabScrollView = tabs;
314        mIncludeTabs = tabs != null;
315        if (mIncludeTabs && mNavigationMode == ActionBar.NAVIGATION_MODE_TABS) {
316            addView(mTabScrollView);
317        }
318    }
319
320    public void setCallback(OnNavigationListener callback) {
321        mCallback = callback;
322    }
323
324    public void setMenu(Menu menu, MenuPresenter.Callback cb) {
325        if (menu == mOptionsMenu) return;
326
327        if (mOptionsMenu != null) {
328            mOptionsMenu.removeMenuPresenter(mActionMenuPresenter);
329            mOptionsMenu.removeMenuPresenter(mExpandedMenuPresenter);
330        }
331
332        MenuBuilder builder = (MenuBuilder) menu;
333        mOptionsMenu = builder;
334        if (mMenuView != null) {
335            removeView(mMenuView);
336        }
337        if (mActionMenuPresenter == null) {
338            mActionMenuPresenter = new ActionMenuPresenter();
339            mActionMenuPresenter.setCallback(cb);
340            mActionMenuPresenter.setId(com.android.internal.R.id.action_menu_presenter);
341            mExpandedMenuPresenter = new ExpandedActionViewMenuPresenter();
342        }
343
344        ActionMenuView menuView;
345        final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
346                LayoutParams.MATCH_PARENT);
347        if (!mSplitActionBar) {
348            builder.addMenuPresenter(mActionMenuPresenter);
349            builder.addMenuPresenter(mExpandedMenuPresenter);
350            menuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this);
351            addView(menuView, layoutParams);
352        } else {
353            // Allow full screen width in split mode.
354            mActionMenuPresenter.setWidthLimit(
355                    getContext().getResources().getDisplayMetrics().widthPixels, true);
356            // No limit to the item count; use whatever will fit.
357            mActionMenuPresenter.setItemLimit(Integer.MAX_VALUE);
358            // Span the whole width
359            layoutParams.width = LayoutParams.MATCH_PARENT;
360            builder.addMenuPresenter(mActionMenuPresenter);
361            builder.addMenuPresenter(mExpandedMenuPresenter);
362            menuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this);
363            if (mSplitView != null) {
364                mSplitView.addView(menuView, layoutParams);
365            } else {
366                // We'll add this later if we missed it this time.
367                menuView.setLayoutParams(layoutParams);
368            }
369        }
370        mMenuView = menuView;
371    }
372
373    public void setCustomNavigationView(View view) {
374        final boolean showCustom = (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0;
375        if (mCustomNavView != null && showCustom) {
376            removeView(mCustomNavView);
377        }
378        mCustomNavView = view;
379        if (mCustomNavView != null && showCustom) {
380            addView(mCustomNavView);
381        }
382    }
383
384    public CharSequence getTitle() {
385        return mTitle;
386    }
387
388    /**
389     * Set the action bar title. This will always replace or override window titles.
390     * @param title Title to set
391     *
392     * @see #setWindowTitle(CharSequence)
393     */
394    public void setTitle(CharSequence title) {
395        mUserTitle = true;
396        setTitleImpl(title);
397    }
398
399    /**
400     * Set the window title. A window title will always be replaced or overridden by a user title.
401     * @param title Title to set
402     *
403     * @see #setTitle(CharSequence)
404     */
405    public void setWindowTitle(CharSequence title) {
406        if (!mUserTitle) {
407            setTitleImpl(title);
408        }
409    }
410
411    private void setTitleImpl(CharSequence title) {
412        mTitle = title;
413        if (mTitleView != null) {
414            mTitleView.setText(title);
415            mTitleLayout.setVisibility(TextUtils.isEmpty(mTitle) && TextUtils.isEmpty(mSubtitle) ?
416                    GONE : VISIBLE);
417        }
418        if (mLogoNavItem != null) {
419            mLogoNavItem.setTitle(title);
420        }
421    }
422
423    public CharSequence getSubtitle() {
424        return mSubtitle;
425    }
426
427    public void setSubtitle(CharSequence subtitle) {
428        mSubtitle = subtitle;
429        if (mSubtitleView != null) {
430            mSubtitleView.setText(subtitle);
431            mSubtitleView.setVisibility(subtitle != null ? VISIBLE : GONE);
432            mTitleLayout.setVisibility(TextUtils.isEmpty(mTitle) && TextUtils.isEmpty(mSubtitle) ?
433                    GONE : VISIBLE);
434        }
435    }
436
437    public void setHomeButtonEnabled(boolean enable) {
438        mHomeLayout.setEnabled(enable);
439        // Make sure the home button has an accurate content description for accessibility.
440        if (!enable) {
441            mHomeLayout.setContentDescription(null);
442        } else if ((mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
443            mHomeLayout.setContentDescription(mContext.getResources().getText(
444                    R.string.action_bar_up_description));
445        } else {
446            mHomeLayout.setContentDescription(mContext.getResources().getText(
447                    R.string.action_bar_home_description));
448        }
449    }
450
451    public void setDisplayOptions(int options) {
452        final int flagsChanged = options ^ mDisplayOptions;
453        mDisplayOptions = options;
454
455        if ((flagsChanged & DISPLAY_RELAYOUT_MASK) != 0) {
456            final boolean showHome = (options & ActionBar.DISPLAY_SHOW_HOME) != 0;
457            final int vis = showHome ? VISIBLE : GONE;
458            mHomeLayout.setVisibility(vis);
459
460            if ((flagsChanged & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
461                final boolean setUp = (options & ActionBar.DISPLAY_HOME_AS_UP) != 0;
462                mHomeLayout.setUp(setUp);
463
464                // Showing home as up implicitly enables interaction with it.
465                // In honeycomb it was always enabled, so make this transition
466                // a bit easier for developers in the common case.
467                // (It would be silly to show it as up without responding to it.)
468                if (setUp) {
469                    setHomeButtonEnabled(true);
470                }
471            }
472
473            if ((flagsChanged & ActionBar.DISPLAY_USE_LOGO) != 0) {
474                final boolean logoVis = mLogo != null && (options & ActionBar.DISPLAY_USE_LOGO) != 0;
475                mHomeLayout.setIcon(logoVis ? mLogo : mIcon);
476            }
477
478            if ((flagsChanged & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
479                if ((options & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
480                    initTitle();
481                } else {
482                    removeView(mTitleLayout);
483                }
484            }
485
486            if (mTitleLayout != null && (flagsChanged &
487                    (ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME)) != 0) {
488                final boolean homeAsUp = (options & ActionBar.DISPLAY_HOME_AS_UP) != 0;
489                final boolean titleUp = homeAsUp && !showHome;
490                mTitleUpView.setVisibility(titleUp ? VISIBLE : GONE);
491                mTitleLayout.setEnabled(titleUp);
492            }
493
494            if ((flagsChanged & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && mCustomNavView != null) {
495                if ((options & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
496                    addView(mCustomNavView);
497                } else {
498                    removeView(mCustomNavView);
499                }
500            }
501
502            requestLayout();
503        } else {
504            invalidate();
505        }
506
507        // Make sure the home button has an accurate content description for accessibility.
508        if (!mHomeLayout.isEnabled()) {
509            mHomeLayout.setContentDescription(null);
510        } else if ((options & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
511            mHomeLayout.setContentDescription(mContext.getResources().getText(
512                    R.string.action_bar_up_description));
513        } else {
514            mHomeLayout.setContentDescription(mContext.getResources().getText(
515                    R.string.action_bar_home_description));
516        }
517    }
518
519    public void setIcon(Drawable icon) {
520        mIcon = icon;
521        if (icon != null &&
522                ((mDisplayOptions & ActionBar.DISPLAY_USE_LOGO) == 0 || mLogo == null)) {
523            mHomeLayout.setIcon(icon);
524        }
525    }
526
527    public void setIcon(int resId) {
528        setIcon(mContext.getResources().getDrawableForDensity(resId, getPreferredIconDensity()));
529    }
530
531    public void setLogo(Drawable logo) {
532        mLogo = logo;
533        if (logo != null && (mDisplayOptions & ActionBar.DISPLAY_USE_LOGO) != 0) {
534            mHomeLayout.setIcon(logo);
535        }
536    }
537
538    public void setLogo(int resId) {
539        mContext.getResources().getDrawable(resId);
540    }
541
542    /**
543     * @return Drawable density to load that will best fit the available height.
544     */
545    private int getPreferredIconDensity() {
546        final Resources res = mContext.getResources();
547        final int availableHeight = getLayoutParams().height -
548                mHomeLayout.getVerticalIconPadding();
549        int iconSize = res.getDimensionPixelSize(android.R.dimen.app_icon_size);
550
551        if (iconSize * DisplayMetrics.DENSITY_LOW >= availableHeight) {
552            return DisplayMetrics.DENSITY_LOW;
553        } else if (iconSize * DisplayMetrics.DENSITY_MEDIUM >= availableHeight) {
554            return DisplayMetrics.DENSITY_MEDIUM;
555        } else if (iconSize * DisplayMetrics.DENSITY_HIGH >= availableHeight) {
556            return DisplayMetrics.DENSITY_HIGH;
557        }
558        return DisplayMetrics.DENSITY_XHIGH;
559    }
560
561    public void setNavigationMode(int mode) {
562        final int oldMode = mNavigationMode;
563        if (mode != oldMode) {
564            switch (oldMode) {
565            case ActionBar.NAVIGATION_MODE_LIST:
566                if (mListNavLayout != null) {
567                    removeView(mListNavLayout);
568                }
569                break;
570            case ActionBar.NAVIGATION_MODE_TABS:
571                if (mTabScrollView != null && mIncludeTabs) {
572                    removeView(mTabScrollView);
573                }
574            }
575
576            switch (mode) {
577            case ActionBar.NAVIGATION_MODE_LIST:
578                if (mSpinner == null) {
579                    mSpinner = new Spinner(mContext, null,
580                            com.android.internal.R.attr.actionDropDownStyle);
581                    mListNavLayout = new LinearLayout(mContext, null,
582                            com.android.internal.R.attr.actionBarTabBarStyle);
583                    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
584                            LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
585                    params.gravity = Gravity.CENTER;
586                    mListNavLayout.addView(mSpinner, params);
587                }
588                if (mSpinner.getAdapter() != mSpinnerAdapter) {
589                    mSpinner.setAdapter(mSpinnerAdapter);
590                }
591                mSpinner.setOnItemSelectedListener(mNavItemSelectedListener);
592                addView(mListNavLayout);
593                break;
594            case ActionBar.NAVIGATION_MODE_TABS:
595                if (mTabScrollView != null && mIncludeTabs) {
596                    addView(mTabScrollView);
597                }
598                break;
599            }
600            mNavigationMode = mode;
601            requestLayout();
602        }
603    }
604
605    public ScrollingTabContainerView createTabContainer() {
606        final LinearLayout tabLayout = new LinearLayout(getContext(), null,
607                com.android.internal.R.attr.actionBarTabBarStyle);
608        tabLayout.setMeasureWithLargestChildEnabled(true);
609        tabLayout.setLayoutParams(new LinearLayout.LayoutParams(
610                LinearLayout.LayoutParams.WRAP_CONTENT, mContentHeight));
611
612        final ScrollingTabContainerView scroller = new ScrollingTabContainerView(mContext);
613        scroller.setTabLayout(tabLayout);
614        return scroller;
615    }
616
617    public void setDropdownAdapter(SpinnerAdapter adapter) {
618        mSpinnerAdapter = adapter;
619        if (mSpinner != null) {
620            mSpinner.setAdapter(adapter);
621        }
622    }
623
624    public SpinnerAdapter getDropdownAdapter() {
625        return mSpinnerAdapter;
626    }
627
628    public void setDropdownSelectedPosition(int position) {
629        mSpinner.setSelection(position);
630    }
631
632    public int getDropdownSelectedPosition() {
633        return mSpinner.getSelectedItemPosition();
634    }
635
636    public View getCustomNavigationView() {
637        return mCustomNavView;
638    }
639
640    public int getNavigationMode() {
641        return mNavigationMode;
642    }
643
644    public int getDisplayOptions() {
645        return mDisplayOptions;
646    }
647
648    @Override
649    protected LayoutParams generateDefaultLayoutParams() {
650        // Used by custom nav views if they don't supply layout params. Everything else
651        // added to an ActionBarView should have them already.
652        return new ActionBar.LayoutParams(DEFAULT_CUSTOM_GRAVITY);
653    }
654
655    @Override
656    protected void onFinishInflate() {
657        super.onFinishInflate();
658
659        addView(mHomeLayout);
660
661        if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
662            final ViewParent parent = mCustomNavView.getParent();
663            if (parent != this) {
664                if (parent instanceof ViewGroup) {
665                    ((ViewGroup) parent).removeView(mCustomNavView);
666                }
667                addView(mCustomNavView);
668            }
669        }
670    }
671
672    private void initTitle() {
673        if (mTitleLayout == null) {
674            LayoutInflater inflater = LayoutInflater.from(getContext());
675            mTitleLayout = (LinearLayout) inflater.inflate(R.layout.action_bar_title_item, null);
676            mTitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_title);
677            mSubtitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_subtitle);
678            mTitleUpView = (View) mTitleLayout.findViewById(R.id.up);
679
680            mTitleLayout.setOnClickListener(mUpClickListener);
681
682            if (mTitleStyleRes != 0) {
683                mTitleView.setTextAppearance(mContext, mTitleStyleRes);
684            }
685            if (mTitle != null) {
686                mTitleView.setText(mTitle);
687            }
688
689            if (mSubtitleStyleRes != 0) {
690                mSubtitleView.setTextAppearance(mContext, mSubtitleStyleRes);
691            }
692            if (mSubtitle != null) {
693                mSubtitleView.setText(mSubtitle);
694                mSubtitleView.setVisibility(VISIBLE);
695            }
696
697            final boolean homeAsUp = (mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0;
698            final boolean titleUp = homeAsUp &&
699                    (mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) == 0;
700            mTitleUpView.setVisibility(titleUp ? VISIBLE : GONE);
701            mTitleLayout.setEnabled(titleUp);
702        }
703
704        addView(mTitleLayout);
705    }
706
707    public void setContextView(ActionBarContextView view) {
708        mContextView = view;
709    }
710
711    public void setCollapsable(boolean collapsable) {
712        mIsCollapsable = collapsable;
713    }
714
715    public boolean isCollapsed() {
716        return mIsCollapsed;
717    }
718
719    @Override
720    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
721        final int childCount = getChildCount();
722        if (mIsCollapsable) {
723            int visibleChildren = 0;
724            for (int i = 0; i < childCount; i++) {
725                final View child = getChildAt(i);
726                if (child.getVisibility() != GONE &&
727                        !(child == mMenuView && mMenuView.getChildCount() == 0)) {
728                    visibleChildren++;
729                }
730            }
731
732            if (visibleChildren == 0) {
733                // No size for an empty action bar when collapsable.
734                setMeasuredDimension(0, 0);
735                mIsCollapsed = true;
736                return;
737            }
738        }
739        mIsCollapsed = false;
740
741        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
742        if (widthMode != MeasureSpec.EXACTLY) {
743            throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
744                    "with android:layout_width=\"match_parent\" (or fill_parent)");
745        }
746
747        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
748        if (heightMode != MeasureSpec.AT_MOST) {
749            throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
750                    "with android:layout_height=\"wrap_content\"");
751        }
752
753        int contentWidth = MeasureSpec.getSize(widthMeasureSpec);
754
755        int maxHeight = mContentHeight > 0 ?
756                mContentHeight : MeasureSpec.getSize(heightMeasureSpec);
757
758        final int verticalPadding = getPaddingTop() + getPaddingBottom();
759        final int paddingLeft = getPaddingLeft();
760        final int paddingRight = getPaddingRight();
761        final int height = maxHeight - verticalPadding;
762        final int childSpecHeight = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
763
764        int availableWidth = contentWidth - paddingLeft - paddingRight;
765        int leftOfCenter = availableWidth / 2;
766        int rightOfCenter = leftOfCenter;
767
768        View homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout;
769
770        if (homeLayout.getVisibility() != GONE) {
771            final LayoutParams lp = homeLayout.getLayoutParams();
772            int homeWidthSpec;
773            if (lp.width < 0) {
774                homeWidthSpec = MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST);
775            } else {
776                homeWidthSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
777            }
778            homeLayout.measure(homeWidthSpec,
779                    MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
780            final int homeWidth = homeLayout.getMeasuredWidth();
781            availableWidth = Math.max(0, availableWidth - homeWidth);
782            leftOfCenter = Math.max(0, availableWidth - homeWidth);
783        }
784
785        if (mMenuView != null && mMenuView.getParent() == this) {
786            availableWidth = measureChildView(mMenuView, availableWidth,
787                    childSpecHeight, 0);
788            rightOfCenter = Math.max(0, rightOfCenter - mMenuView.getMeasuredWidth());
789        }
790
791        if (mExpandedActionView == null) {
792            boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
793                    (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
794            if (showTitle) {
795                availableWidth = measureChildView(mTitleLayout, availableWidth, childSpecHeight, 0);
796                leftOfCenter = Math.max(0, leftOfCenter - mTitleLayout.getMeasuredWidth());
797            }
798
799            switch (mNavigationMode) {
800                case ActionBar.NAVIGATION_MODE_LIST:
801                    if (mListNavLayout != null) {
802                        final int itemPaddingSize = showTitle ? mItemPadding * 2 : mItemPadding;
803                        availableWidth = Math.max(0, availableWidth - itemPaddingSize);
804                        leftOfCenter = Math.max(0, leftOfCenter - itemPaddingSize);
805                        mListNavLayout.measure(
806                                MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
807                                MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
808                        final int listNavWidth = mListNavLayout.getMeasuredWidth();
809                        availableWidth = Math.max(0, availableWidth - listNavWidth);
810                        leftOfCenter = Math.max(0, leftOfCenter - listNavWidth);
811                    }
812                    break;
813                case ActionBar.NAVIGATION_MODE_TABS:
814                    if (mTabScrollView != null) {
815                        final int itemPaddingSize = showTitle ? mItemPadding * 2 : mItemPadding;
816                        availableWidth = Math.max(0, availableWidth - itemPaddingSize);
817                        leftOfCenter = Math.max(0, leftOfCenter - itemPaddingSize);
818                        mTabScrollView.measure(
819                                MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
820                                MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
821                        final int tabWidth = mTabScrollView.getMeasuredWidth();
822                        availableWidth = Math.max(0, availableWidth - tabWidth);
823                        leftOfCenter = Math.max(0, leftOfCenter - tabWidth);
824                    }
825                    break;
826            }
827        }
828
829        if (mIndeterminateProgressView != null &&
830                mIndeterminateProgressView.getVisibility() != GONE) {
831            availableWidth = measureChildView(mIndeterminateProgressView, availableWidth,
832                    childSpecHeight, 0);
833            rightOfCenter = Math.max(0,
834                    rightOfCenter - mIndeterminateProgressView.getMeasuredWidth());
835        }
836
837        View customView = null;
838        if (mExpandedActionView != null) {
839            customView = mExpandedActionView;
840        } else if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 &&
841                mCustomNavView != null) {
842            customView = mCustomNavView;
843        }
844
845        if (customView != null) {
846            final LayoutParams lp = generateLayoutParams(customView.getLayoutParams());
847            final ActionBar.LayoutParams ablp = lp instanceof ActionBar.LayoutParams ?
848                    (ActionBar.LayoutParams) lp : null;
849
850            int horizontalMargin = 0;
851            int verticalMargin = 0;
852            if (ablp != null) {
853                horizontalMargin = ablp.leftMargin + ablp.rightMargin;
854                verticalMargin = ablp.topMargin + ablp.bottomMargin;
855            }
856
857            // If the action bar is wrapping to its content height, don't allow a custom
858            // view to MATCH_PARENT.
859            int customNavHeightMode;
860            if (mContentHeight <= 0) {
861                customNavHeightMode = MeasureSpec.AT_MOST;
862            } else {
863                customNavHeightMode = lp.height != LayoutParams.WRAP_CONTENT ?
864                        MeasureSpec.EXACTLY : MeasureSpec.AT_MOST;
865            }
866            final int customNavHeight = Math.max(0,
867                    (lp.height >= 0 ? Math.min(lp.height, height) : height) - verticalMargin);
868
869            final int customNavWidthMode = lp.width != LayoutParams.WRAP_CONTENT ?
870                    MeasureSpec.EXACTLY : MeasureSpec.AT_MOST;
871            int customNavWidth = Math.max(0,
872                    (lp.width >= 0 ? Math.min(lp.width, availableWidth) : availableWidth)
873                    - horizontalMargin);
874            final int hgrav = (ablp != null ? ablp.gravity : DEFAULT_CUSTOM_GRAVITY) &
875                    Gravity.HORIZONTAL_GRAVITY_MASK;
876
877            // Centering a custom view is treated specially; we try to center within the whole
878            // action bar rather than in the available space.
879            if (hgrav == Gravity.CENTER_HORIZONTAL && lp.width == LayoutParams.MATCH_PARENT) {
880                customNavWidth = Math.min(leftOfCenter, rightOfCenter) * 2;
881            }
882
883            customView.measure(
884                    MeasureSpec.makeMeasureSpec(customNavWidth, customNavWidthMode),
885                    MeasureSpec.makeMeasureSpec(customNavHeight, customNavHeightMode));
886        }
887
888        if (mContentHeight <= 0) {
889            int measuredHeight = 0;
890            for (int i = 0; i < childCount; i++) {
891                View v = getChildAt(i);
892                int paddedViewHeight = v.getMeasuredHeight() + verticalPadding;
893                if (paddedViewHeight > measuredHeight) {
894                    measuredHeight = paddedViewHeight;
895                }
896            }
897            setMeasuredDimension(contentWidth, measuredHeight);
898        } else {
899            setMeasuredDimension(contentWidth, maxHeight);
900        }
901
902        if (mContextView != null) {
903            mContextView.setHeight(getMeasuredHeight());
904        }
905
906        if (mProgressView != null && mProgressView.getVisibility() != GONE) {
907            mProgressView.measure(MeasureSpec.makeMeasureSpec(
908                    contentWidth - mProgressBarPadding * 2, MeasureSpec.EXACTLY),
909                    MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST));
910        }
911    }
912
913    @Override
914    protected void onLayout(boolean changed, int l, int t, int r, int b) {
915        int x = getPaddingLeft();
916        final int y = getPaddingTop();
917        final int contentHeight = b - t - getPaddingTop() - getPaddingBottom();
918
919        if (contentHeight <= 0) {
920            // Nothing to do if we can't see anything.
921            return;
922        }
923
924        View homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout;
925        if (homeLayout.getVisibility() != GONE) {
926            x += positionChild(homeLayout, x, y, contentHeight);
927        }
928
929        if (mExpandedActionView == null) {
930            final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
931                    (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
932            if (showTitle) {
933                x += positionChild(mTitleLayout, x, y, contentHeight);
934            }
935
936            switch (mNavigationMode) {
937                case ActionBar.NAVIGATION_MODE_STANDARD:
938                    break;
939                case ActionBar.NAVIGATION_MODE_LIST:
940                    if (mListNavLayout != null) {
941                        if (showTitle) x += mItemPadding;
942                        x += positionChild(mListNavLayout, x, y, contentHeight) + mItemPadding;
943                    }
944                    break;
945                case ActionBar.NAVIGATION_MODE_TABS:
946                    if (mTabScrollView != null) {
947                        if (showTitle) x += mItemPadding;
948                        x += positionChild(mTabScrollView, x, y, contentHeight) + mItemPadding;
949                    }
950                    break;
951            }
952        }
953
954        int menuLeft = r - l - getPaddingRight();
955        if (mMenuView != null && mMenuView.getParent() == this) {
956            positionChildInverse(mMenuView, menuLeft, y, contentHeight);
957            menuLeft -= mMenuView.getMeasuredWidth();
958        }
959
960        if (mIndeterminateProgressView != null &&
961                mIndeterminateProgressView.getVisibility() != GONE) {
962            positionChildInverse(mIndeterminateProgressView, menuLeft, y, contentHeight);
963            menuLeft -= mIndeterminateProgressView.getMeasuredWidth();
964        }
965
966        View customView = null;
967        if (mExpandedActionView != null) {
968            customView = mExpandedActionView;
969        } else if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 &&
970                mCustomNavView != null) {
971            customView = mCustomNavView;
972        }
973        if (customView != null) {
974            LayoutParams lp = customView.getLayoutParams();
975            final ActionBar.LayoutParams ablp = lp instanceof ActionBar.LayoutParams ?
976                    (ActionBar.LayoutParams) lp : null;
977
978            final int gravity = ablp != null ? ablp.gravity : DEFAULT_CUSTOM_GRAVITY;
979            final int navWidth = customView.getMeasuredWidth();
980
981            int topMargin = 0;
982            int bottomMargin = 0;
983            if (ablp != null) {
984                x += ablp.leftMargin;
985                menuLeft -= ablp.rightMargin;
986                topMargin = ablp.topMargin;
987                bottomMargin = ablp.bottomMargin;
988            }
989
990            int hgravity = gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
991            // See if we actually have room to truly center; if not push against left or right.
992            if (hgravity == Gravity.CENTER_HORIZONTAL) {
993                final int centeredLeft = ((mRight - mLeft) - navWidth) / 2;
994                if (centeredLeft < x) {
995                    hgravity = Gravity.LEFT;
996                } else if (centeredLeft + navWidth > menuLeft) {
997                    hgravity = Gravity.RIGHT;
998                }
999            }
1000
1001            int xpos = 0;
1002            switch (hgravity) {
1003                case Gravity.CENTER_HORIZONTAL:
1004                    xpos = ((mRight - mLeft) - navWidth) / 2;
1005                    break;
1006                case Gravity.LEFT:
1007                    xpos = x;
1008                    break;
1009                case Gravity.RIGHT:
1010                    xpos = menuLeft - navWidth;
1011                    break;
1012            }
1013
1014            int ypos = 0;
1015            switch (gravity & Gravity.VERTICAL_GRAVITY_MASK) {
1016                case Gravity.CENTER_VERTICAL:
1017                    final int paddedTop = getPaddingTop();
1018                    final int paddedBottom = mBottom - mTop - getPaddingBottom();
1019                    ypos = ((paddedBottom - paddedTop) - customView.getMeasuredHeight()) / 2;
1020                    break;
1021                case Gravity.TOP:
1022                    ypos = getPaddingTop() + topMargin;
1023                    break;
1024                case Gravity.BOTTOM:
1025                    ypos = getHeight() - getPaddingBottom() - customView.getMeasuredHeight()
1026                            - bottomMargin;
1027                    break;
1028            }
1029            final int customWidth = customView.getMeasuredWidth();
1030            customView.layout(xpos, ypos, xpos + customWidth,
1031                    ypos + customView.getMeasuredHeight());
1032            x += customWidth;
1033        }
1034
1035        if (mProgressView != null) {
1036            mProgressView.bringToFront();
1037            final int halfProgressHeight = mProgressView.getMeasuredHeight() / 2;
1038            mProgressView.layout(mProgressBarPadding, -halfProgressHeight,
1039                    mProgressBarPadding + mProgressView.getMeasuredWidth(), halfProgressHeight);
1040        }
1041    }
1042
1043    @Override
1044    public LayoutParams generateLayoutParams(LayoutParams lp) {
1045        if (lp == null) {
1046            lp = generateDefaultLayoutParams();
1047        }
1048        return lp;
1049    }
1050
1051    @Override
1052    public Parcelable onSaveInstanceState() {
1053        Parcelable superState = super.onSaveInstanceState();
1054        SavedState state = new SavedState(superState);
1055
1056        if (mExpandedMenuPresenter != null && mExpandedMenuPresenter.mCurrentExpandedItem != null) {
1057            state.expandedMenuItemId = mExpandedMenuPresenter.mCurrentExpandedItem.getItemId();
1058        }
1059
1060        state.isOverflowOpen = isOverflowMenuShowing();
1061
1062        return state;
1063    }
1064
1065    @Override
1066    public void onRestoreInstanceState(Parcelable p) {
1067        SavedState state = (SavedState) p;
1068
1069        super.onRestoreInstanceState(state.getSuperState());
1070
1071        if (state.expandedMenuItemId != 0 &&
1072                mExpandedMenuPresenter != null && mOptionsMenu != null) {
1073            final MenuItem item = mOptionsMenu.findItem(state.expandedMenuItemId);
1074            if (item != null) {
1075                item.expandActionView();
1076            }
1077        }
1078
1079        if (state.isOverflowOpen) {
1080            postShowOverflowMenu();
1081        }
1082    }
1083
1084    static class SavedState extends BaseSavedState {
1085        int expandedMenuItemId;
1086        boolean isOverflowOpen;
1087
1088        SavedState(Parcelable superState) {
1089            super(superState);
1090        }
1091
1092        private SavedState(Parcel in) {
1093            super(in);
1094            expandedMenuItemId = in.readInt();
1095            isOverflowOpen = in.readInt() != 0;
1096        }
1097
1098        @Override
1099        public void writeToParcel(Parcel out, int flags) {
1100            super.writeToParcel(out, flags);
1101            out.writeInt(expandedMenuItemId);
1102            out.writeInt(isOverflowOpen ? 1 : 0);
1103        }
1104
1105        public static final Parcelable.Creator<SavedState> CREATOR =
1106                new Parcelable.Creator<SavedState>() {
1107            public SavedState createFromParcel(Parcel in) {
1108                return new SavedState(in);
1109            }
1110
1111            public SavedState[] newArray(int size) {
1112                return new SavedState[size];
1113            }
1114        };
1115    }
1116
1117    private static class HomeView extends FrameLayout {
1118        private View mUpView;
1119        private ImageView mIconView;
1120
1121        public HomeView(Context context) {
1122            this(context, null);
1123        }
1124
1125        public HomeView(Context context, AttributeSet attrs) {
1126            super(context, attrs);
1127        }
1128
1129        public void setUp(boolean isUp) {
1130            mUpView.setVisibility(isUp ? VISIBLE : GONE);
1131        }
1132
1133        public void setIcon(Drawable icon) {
1134            mIconView.setImageDrawable(icon);
1135        }
1136
1137        @Override
1138        protected void onFinishInflate() {
1139            mUpView = findViewById(com.android.internal.R.id.up);
1140            mIconView = (ImageView) findViewById(com.android.internal.R.id.home);
1141        }
1142
1143        public int getVerticalIconPadding() {
1144            return mIconView.getPaddingTop() + mIconView.getPaddingBottom();
1145        }
1146
1147        @Override
1148        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
1149            measureChildWithMargins(mUpView, widthMeasureSpec, 0, heightMeasureSpec, 0);
1150            final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams();
1151            int width = upLp.leftMargin + mUpView.getMeasuredWidth() + upLp.rightMargin;
1152            int height = upLp.topMargin + mUpView.getMeasuredHeight() + upLp.bottomMargin;
1153            measureChildWithMargins(mIconView, widthMeasureSpec, width, heightMeasureSpec, 0);
1154            final LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams();
1155            width += iconLp.leftMargin + mIconView.getMeasuredWidth() + iconLp.rightMargin;
1156            height = Math.max(height,
1157                    iconLp.topMargin + mIconView.getMeasuredHeight() + iconLp.bottomMargin);
1158
1159            final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
1160            final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
1161            final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
1162            final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
1163
1164            switch (widthMode) {
1165                case MeasureSpec.AT_MOST:
1166                    width = Math.min(width, widthSize);
1167                    break;
1168                case MeasureSpec.EXACTLY:
1169                    width = widthSize;
1170                    break;
1171                case MeasureSpec.UNSPECIFIED:
1172                default:
1173                    break;
1174            }
1175            switch (heightMode) {
1176                case MeasureSpec.AT_MOST:
1177                    height = Math.min(height, heightSize);
1178                    break;
1179                case MeasureSpec.EXACTLY:
1180                    height = heightSize;
1181                    break;
1182                case MeasureSpec.UNSPECIFIED:
1183                default:
1184                    break;
1185            }
1186            setMeasuredDimension(width, height);
1187        }
1188
1189        @Override
1190        protected void onLayout(boolean changed, int l, int t, int r, int b) {
1191            final int vCenter = (b - t) / 2;
1192            int width = r - l;
1193            int upOffset = 0;
1194            if (mUpView.getVisibility() != GONE) {
1195                final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams();
1196                final int upHeight = mUpView.getMeasuredHeight();
1197                final int upWidth = mUpView.getMeasuredWidth();
1198                final int upTop = vCenter - upHeight / 2;
1199                mUpView.layout(0, upTop, upWidth, upTop + upHeight);
1200                upOffset = upLp.leftMargin + upWidth + upLp.rightMargin;
1201                width -= upOffset;
1202                l += upOffset;
1203            }
1204            final LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams();
1205            final int iconHeight = mIconView.getMeasuredHeight();
1206            final int iconWidth = mIconView.getMeasuredWidth();
1207            final int hCenter = (r - l) / 2;
1208            final int iconLeft = upOffset + Math.max(iconLp.leftMargin, hCenter - iconWidth / 2);
1209            final int iconTop = Math.max(iconLp.topMargin, vCenter - iconHeight / 2);
1210            mIconView.layout(iconLeft, iconTop, iconLeft + iconWidth, iconTop + iconHeight);
1211        }
1212    }
1213
1214    private class ExpandedActionViewMenuPresenter implements MenuPresenter {
1215        MenuBuilder mMenu;
1216        MenuItemImpl mCurrentExpandedItem;
1217
1218        @Override
1219        public void initForMenu(Context context, MenuBuilder menu) {
1220            // Clear the expanded action view when menus change.
1221            mExpandedActionView = null;
1222            if (mCurrentExpandedItem != null) {
1223                mCurrentExpandedItem.collapseActionView();
1224            }
1225            mMenu = menu;
1226        }
1227
1228        @Override
1229        public MenuView getMenuView(ViewGroup root) {
1230            return null;
1231        }
1232
1233        @Override
1234        public void updateMenuView(boolean cleared) {
1235            // Make sure the expanded item we have is still there.
1236            if (mCurrentExpandedItem != null) {
1237                boolean found = false;
1238                final int count = mMenu.size();
1239                for (int i = 0; i < count; i++) {
1240                    final MenuItem item = mMenu.getItem(i);
1241                    if (item == mCurrentExpandedItem) {
1242                        found = true;
1243                        break;
1244                    }
1245                }
1246
1247                if (!found) {
1248                    // The item we had expanded disappeared. Collapse.
1249                    collapseItemActionView(mMenu, mCurrentExpandedItem);
1250                }
1251            }
1252        }
1253
1254        @Override
1255        public void setCallback(Callback cb) {
1256        }
1257
1258        @Override
1259        public boolean onSubMenuSelected(SubMenuBuilder subMenu) {
1260            return false;
1261        }
1262
1263        @Override
1264        public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
1265        }
1266
1267        @Override
1268        public boolean flagActionItems() {
1269            return false;
1270        }
1271
1272        @Override
1273        public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) {
1274            mExpandedActionView = item.getActionView();
1275            mExpandedHomeLayout.setIcon(item.getIcon());
1276            mCurrentExpandedItem = item;
1277            if (mExpandedActionView.getParent() != ActionBarView.this) {
1278                addView(mExpandedActionView);
1279            }
1280            if (mExpandedHomeLayout.getParent() != ActionBarView.this) {
1281                addView(mExpandedHomeLayout);
1282            }
1283            mHomeLayout.setVisibility(GONE);
1284            if (mTitleLayout != null) mTitleLayout.setVisibility(GONE);
1285            if (mTabScrollView != null) mTabScrollView.setVisibility(GONE);
1286            if (mSpinner != null) mSpinner.setVisibility(GONE);
1287            if (mCustomNavView != null) mCustomNavView.setVisibility(GONE);
1288            requestLayout();
1289            item.setActionViewExpanded(true);
1290            return true;
1291        }
1292
1293        @Override
1294        public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) {
1295            removeView(mExpandedActionView);
1296            removeView(mExpandedHomeLayout);
1297            if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) != 0) {
1298                mHomeLayout.setVisibility(VISIBLE);
1299            }
1300            if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
1301                if (mTitleLayout == null) {
1302                    initTitle();
1303                } else {
1304                    mTitleLayout.setVisibility(VISIBLE);
1305                }
1306            }
1307            if (mTabScrollView != null && mNavigationMode == ActionBar.NAVIGATION_MODE_TABS) {
1308                mTabScrollView.setVisibility(VISIBLE);
1309            }
1310            if (mSpinner != null && mNavigationMode == ActionBar.NAVIGATION_MODE_LIST) {
1311                mSpinner.setVisibility(VISIBLE);
1312            }
1313            if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
1314                mCustomNavView.setVisibility(VISIBLE);
1315            }
1316            mExpandedActionView = null;
1317            mExpandedHomeLayout.setIcon(null);
1318            mCurrentExpandedItem = null;
1319            requestLayout();
1320            item.setActionViewExpanded(false);
1321            return true;
1322        }
1323
1324        @Override
1325        public int getId() {
1326            return 0;
1327        }
1328
1329        @Override
1330        public Parcelable onSaveInstanceState() {
1331            return null;
1332        }
1333
1334        @Override
1335        public void onRestoreInstanceState(Parcelable state) {
1336        }
1337    }
1338}
1339