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